caddydiscord

package module
v1.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 11, 2023 License: AGPL-3.0 Imports: 17 Imported by: 0

README

Caddy - Discord

tl;dr: Authenticate caddy routes based on a Discord User Identity.
e.g. Accessing /really-cool-people requires user to have {Role} within {Guild}

This package contains a module allowing authorization in Caddy based on a Discord Identity, by using Discords OAuth2 flow (authorization code grant).


caddy-discord is licensed under GNU Affero General Public License v3.0


Caddy Modules
caddydiscord
http.authentication.providers.discord
http.handler.discord

Docker (Container)

docker run -p 8080:8080 \
  --rm -v $PWD/Caddyfile:/etc/caddy/Caddyfile \
  enumgg/caddy-discord:v1.0.1

Discord Resources

realm allows you name a label and group together specific targeted Discord Users by using the directives below.

Resource Description Example
User ID Discord User IDs (optionally with guild presence)
realm godmode {
user 314009111187026172 # Allow user regardless of which guild they are in
guild 1063070451111289907 {
user 314009111187026199 # Allow user if they're part of guild
}
}
Guild Any user that exists within the guild
realm cool_guild_users {
guild 1063070451111289907 {
* # Allows all users
}
}
Role Users that assigned a specific role within a guild
realm cool_role {
guild 1063070451111289907 {
role 106301111332755034
role 106301111332755034
}
}

Loosely inspired from caddy-security's Discord OAuth2 module, with a much stronger focus on coupling Discord and Caddy for authentication purposes.


Discord server

Install

Download Latest Version

  1. Download caddy + caddy-discord
    • Using released binaries
    • Build yourself using xcaddy
      • xcaddy build --with github.com/enum-gg/caddy-discord
  2. Create Discord Application (Discord Developer Portal)
    • New Application
    • OAuth2
      • Obtain your Client ID & Client secret
      • Add Redirects Docs
  3. Prepare your Caddyfile
    • Gather your Discord App OAuth2 Client ID & Client Secret,
    • Decide your route for caddy-discords to use as the OAuth2

Caddyfile Example

{
    discord {
        client_id 1000000000000000000 # Discord app OAuth client ID 
        client_secret 8CEPZZZZZAfl_w19ZZZZW_k # Discord app OAuth secret
        redirect http://localhost:8080/discord/callback # Route you've configured with `discordauth callback`

        realm clique {
            guild 106307051119907 {
                role 10630111112755034
            }
        }
        
        realm just_for_me {
            user 31400111187026172
        }
    }
}

http://localhost:8080 {
    route /discord/callback {
         # Desigate route as OAuth callback endpoint
         discord callback 
   }

    route /discordians-only {
         # Only allow discord users that auth against 'really_cool_area' realm 
         protect using clique 
        
         respond "Hello {http.auth.user.username}!<br /><br /><img src='https://cdn.discordapp.com/avatars/{http.auth.user.id}/{http.auth.user.avatar}?size=4096.png'> "
    }

    respond "Hello, world!"
}

Building

xcaddy build --with github.com/enum-gg/caddy-discord=./

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewAuthFlowToken

func NewAuthFlowToken(redirectURI string, realm string, exp time.Time) *jwt.Token

func NewAuthedTokenParser

func NewAuthedTokenParser(key []byte) func(signedToken string) (*AuthenticatedClaims, error)

func NewAuthenticatedToken

func NewAuthenticatedToken(identity discord.User, realm string, exp time.Time) *jwt.Token

func NewFlowTokenParser

func NewFlowTokenParser(key []byte) func(signedToken string) (*FlowTokenParser, error)

func ResourceRequiresGuild

func ResourceRequiresGuild(resource DiscordResource) bool

func RoleChecker added in v1.1.1

func RoleChecker(desiredRoleID string, roles []string) string

Types

type AccessIdentifier

type AccessIdentifier struct {
	Resource   DiscordResource `json:"Resource"` // role, user
	Identifier string          `json:"Identifier,omitempty"`
	GuildID    string          `json:"GuildID,omitempty"`
	Wildcard   bool            `json:"Wildcard,omitempty"`
}

type AuthedTokenParserSignature

type AuthedTokenParserSignature = func(signedToken string) (*AuthenticatedClaims, error)

type AuthenticatedClaims

type AuthenticatedClaims struct {
	Realm string `json:"realm,omitempty"`

	Username string `json:"user,omitempty"`
	Avatar   string `json:"avatar,omitempty"`
	jwt.RegisteredClaims
}

func (AuthenticatedClaims) GetAudience

func (a AuthenticatedClaims) GetAudience() string

type CustomClaim

type CustomClaim interface {
	jwt.Claims
}

type DiscordAuthPlugin

type DiscordAuthPlugin struct {
	Configuration []string
	OAuth         *oauth2.Config
	Realms        *RealmRegistry
	Key           string
	// contains filtered or unexported fields
}

func (DiscordAuthPlugin) CaddyModule

func (DiscordAuthPlugin) CaddyModule() caddy.ModuleInfo

func (*DiscordAuthPlugin) Provision

func (s *DiscordAuthPlugin) Provision(ctx caddy.Context) error

func (DiscordAuthPlugin) ServeHTTP

ServeHTTP implements caddyhttp.MiddlewareHandler.

func (*DiscordAuthPlugin) UnmarshalCaddyfile

func (s *DiscordAuthPlugin) UnmarshalCaddyfile(d *caddyfile.Dispenser) error

UnmarshalCaddyfile will extract discordauth directives on a server-level

route /some/path/callback {
    discordauth callback
}

func (*DiscordAuthPlugin) Validate

func (s *DiscordAuthPlugin) Validate() error

type DiscordPortalApp

type DiscordPortalApp struct {
	ClientID     string        `json:"clientID"`
	ClientSecret string        `json:"clientSecret"`
	RedirectURL  string        `json:"redirectURL"`
	Realms       RealmRegistry `json:"realms"`

	Key string `json:"key,omitempty"`
	// contains filtered or unexported fields
}

func (DiscordPortalApp) CaddyModule

func (DiscordPortalApp) CaddyModule() caddy.ModuleInfo

CaddyModule returns the Caddy module information.

func (*DiscordPortalApp) Provision

func (d *DiscordPortalApp) Provision(_ caddy.Context) error

func (DiscordPortalApp) Start

func (d DiscordPortalApp) Start() error

func (DiscordPortalApp) Stop

func (d DiscordPortalApp) Stop() error

Stop stops the App.

func (DiscordPortalApp) Validate

func (d DiscordPortalApp) Validate() error

type DiscordResource

type DiscordResource int
const (
	Unknown          DiscordResource = 0
	DiscordGuildRule DiscordResource = 1
	DiscordRoleRule  DiscordResource = 2
	// DiscordMemberRule represents a specific Discord User within a specific guild
	DiscordMemberRule DiscordResource = 3
	// DiscordUserRule represents a Discord User Snowflake ID
	DiscordUserRule DiscordResource = 4
)

type FlowTokenParser

type FlowTokenParser struct {
	Realm       string `json:"realm,omitempty"`
	RedirectURI string `json:"redirectURI,omitempty"`
	jwt.RegisteredClaims
}

func (FlowTokenParser) GetAudience

func (f FlowTokenParser) GetAudience() string

type FlowTokenParserSignature

type FlowTokenParserSignature = func(signedToken string) (*FlowTokenParser, error)

type JWTManager

type JWTManager struct {
	// contains filtered or unexported fields
}

type ProtectCfg

type ProtectCfg struct {
	ClientID     string
	ClientSecret string
}

type ProtectorPlugin

type ProtectorPlugin struct {
	OAuthConfig *oauth2.Config

	Realm string
	// contains filtered or unexported fields
}

func (ProtectorPlugin) Authenticate

Authenticate implements caddyhttp.MiddlewareHandler.

func (ProtectorPlugin) CaddyModule

func (ProtectorPlugin) CaddyModule() caddy.ModuleInfo

func (*ProtectorPlugin) Provision

func (p *ProtectorPlugin) Provision(ctx caddy.Context) error

func (*ProtectorPlugin) UnmarshalCaddyfile

func (p *ProtectorPlugin) UnmarshalCaddyfile(d *caddyfile.Dispenser) error

func (*ProtectorPlugin) Validate

func (p *ProtectorPlugin) Validate() error

type Realm

type Realm struct {
	Ref         string              `json:"Ref"`
	Identifiers []*AccessIdentifier `json:"Identifiers"`
}

func (Realm) GetAllGuilds

func (r Realm) GetAllGuilds() []string

type RealmBuilder

type RealmBuilder struct {
	// contains filtered or unexported fields
}

func NewRealmBuilder

func NewRealmBuilder() RealmBuilder

func (RealmBuilder) AllowAllDiscordUsers

func (r RealmBuilder) AllowAllDiscordUsers()

func (RealmBuilder) AllowAllGuildMembers

func (r RealmBuilder) AllowAllGuildMembers(guildID string)

func (RealmBuilder) AllowDiscordUser

func (r RealmBuilder) AllowDiscordUser(userID string)

func (RealmBuilder) AllowGuildMember

func (r RealmBuilder) AllowGuildMember(guildID string, userID string)

func (RealmBuilder) AllowGuildRole

func (r RealmBuilder) AllowGuildRole(guildID string, roleID string)

func (RealmBuilder) Build

func (r RealmBuilder) Build() *Realm

func (RealmBuilder) Name

func (r RealmBuilder) Name(name string)

type RealmRegistry

type RealmRegistry []*Realm

func (RealmRegistry) ByName

func (r RealmRegistry) ByName(name string) *Realm

type TokenSignerSignature

type TokenSignerSignature = func(token *jwt.Token) (string, error)

func NewTokenSigner

func NewTokenSigner(key []byte) TokenSignerSignature

Directories

Path Synopsis
cmd
caddy
Package main is the entry point of the Caddy application.
Package main is the entry point of the Caddy application.
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL