Skip to content

Commit

Permalink
refactor(auth): add comments and remove useless method override
Browse files Browse the repository at this point in the history
  • Loading branch information
Darkness4 committed Nov 21, 2023
1 parent 333ea1e commit b133cf5
Show file tree
Hide file tree
Showing 14 changed files with 132 additions and 65 deletions.
45 changes: 45 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
linters:
enable:
# Drop-in replacement of `golint`.
- revive

issues:
include:
- EXC0012
- EXC0015

run:
skip-files:
- metascheduler/metascheduler_error.go

linters-settings:
staticcheck:
checks: ['all']
revive:
severity: error
confidence: 0.7
rules:
- name: blank-imports
- name: context-as-argument
- name: context-keys-type
- name: dot-imports
- name: empty-block
- name: errorf
- name: error-return
- name: error-strings
- name: error-naming
- name: exported
- name: if-return
- name: increment-decrement
- name: indent-error-flow
- name: package-comments
- name: range
- name: receiver-naming
- name: redefines-builtin-id
- name: superfluous-else
- name: time-naming
- name: unexported-return
- name: unused-parameter
- name: unreachable-code
- name: var-declaration
- name: var-naming
13 changes: 8 additions & 5 deletions auth/auth.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package auth defines the authentication layer of the application.
package auth

import (
Expand All @@ -14,15 +15,14 @@ import (
)

const (
userURL = "https://api.github.com/user"

tokenCookieKey = "session_token"
)

type claimsContextKey struct{}

// Auth is a service that provides HTTP handlers and middlewares used for authentication.
type Auth struct {
JWT jwt.Service
JWTSecret jwt.Secret
Providers map[string]Provider
}

Expand Down Expand Up @@ -115,7 +115,7 @@ func (a *Auth) CallBack() http.HandlerFunc {
return
}

token, err := a.JWT.GenerateToken(userID, userName)
token, err := a.JWTSecret.GenerateToken(userID, userName)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
Expand All @@ -132,6 +132,7 @@ func (a *Auth) CallBack() http.HandlerFunc {
}
}

// Logout removes session cookies and redirect to home.
func (a *Auth) Logout() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie(tokenCookieKey)
Expand All @@ -146,6 +147,7 @@ func (a *Auth) Logout() http.HandlerFunc {
}
}

// Middleware is an authentication guard for HTTP servers.
func (a *Auth) Middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Get the JWT token from the request header
Expand All @@ -156,7 +158,7 @@ func (a *Auth) Middleware(next http.Handler) http.Handler {
}

// Verify the JWT token
claims, err := a.JWT.VerifyToken(cookie.Value)
claims, err := a.JWTSecret.VerifyToken(cookie.Value)
if err != nil {
log.Error().Err(err).Msg("token verification failed")
next.ServeHTTP(w, r)
Expand All @@ -169,6 +171,7 @@ func (a *Auth) Middleware(next http.Handler) http.Handler {
})
}

// GetClaimsFromRequest is a helper function to fetch the JWT session token from an HTTP request.
func GetClaimsFromRequest(r *http.Request) (claims *jwt.Claims, ok bool) {
claims, ok = r.Context().Value(claimsContextKey{}).(*jwt.Claims)
return claims, ok
Expand Down
15 changes: 13 additions & 2 deletions auth/auth_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import (
"golang.org/x/oauth2/github"
)

// Config is the authentication configuration definition for the application.
type Config struct {
Providers []ProviderConfig `yaml:"providers"`
}

// ProviderConfig is the configuration of one provider to achieve the OAuth2 flow.
type ProviderConfig struct {
Type ProviderType `yaml:"type"`
Name string `yaml:"name"`
Expand All @@ -23,30 +25,39 @@ type ProviderConfig struct {
Endpoint string `yaml:"endpoint"`
}

// ProviderType is a string uses the indentify edge cases in authentication.
type ProviderType string

const (
ProviderGitHub = "github"
ProviderOIDC = "oidc"
// ProviderGitHub is the type of the authentication provider that uses GitHub OAuth2.
ProviderGitHub ProviderType = "github"
// ProviderOIDC is the generic type of authentication provider that uses OIDC.
ProviderOIDC ProviderType = "oidc"
)

// Provider is the interface that defines the necessary methods of authentication providers.
type Provider interface {
// AuthCodeURL returns the URL of the consent page that asks for permissions.
AuthCodeURL(state string, opts ...oauth2.AuthCodeOption) string
// Exchange converts a code into an OAuth2 token.
Exchange(ctx context.Context, code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error)

// DisplayName is the provider's name that can be displayed publicly.
DisplayName() string
GetIdentity(
ctx context.Context,
token *oauth2.Token,
) (userID string, userName string, err error)
}

// OIDCClaims are the standard fields given by an OIDC provider.
type OIDCClaims struct {
jwt.RegisteredClaims
Name string `json:"name"`
Email string `json:"email"`
}

// GenerateProviders generates a map of provider based on the given configuration.
func GenerateProviders(
ctx context.Context,
config Config,
Expand Down
23 changes: 10 additions & 13 deletions auth/auth_github_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,24 @@ import (
"golang.org/x/oauth2"
)

const (
githubUserURL = "https://api.github.com/user"
)

// GitHubProvider is a authentication provider which uses OAuth2 from GitHub and GitHub API as identity provider.
type GitHubProvider struct {
Name string
*oauth2.Config
}

func (p *GitHubProvider) AuthCodeURL(state string, opts ...oauth2.AuthCodeOption) string {
return p.Config.AuthCodeURL(state, opts...)
}

func (p *GitHubProvider) Exchange(
ctx context.Context,
code string,
opts ...oauth2.AuthCodeOption,
) (*oauth2.Token, error) {
return p.Config.Exchange(ctx, code, opts...)
}

// DisplayName returns the display name of the provider.
func (p *GitHubProvider) DisplayName() string {
return p.Name
}

// GetIdentity fetches the identity of the authenticated user from the GitHub API.
//
// It returns <provider>:<user id>.
func (p *GitHubProvider) GetIdentity(
ctx context.Context,
token *oauth2.Token,
Expand All @@ -48,7 +45,7 @@ type githubUser struct {
}

func getGithubUser(ctx context.Context, accessToken string) (githubUser, error) {
req, err := http.NewRequest("GET", userURL, nil)
req, err := http.NewRequest("GET", githubUserURL, nil)
if err != nil {
return githubUser{}, err
}
Expand Down
17 changes: 5 additions & 12 deletions auth/auth_oidc_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,22 @@ import (
"golang.org/x/oauth2"
)

// OIDCProvider is a authentication provider which uses OpenID Connect.
type OIDCProvider struct {
Name string
*oauth2.Config

*oidc.Provider
}

func (p *OIDCProvider) AuthCodeURL(state string, opts ...oauth2.AuthCodeOption) string {
return p.Config.AuthCodeURL(state, opts...)
}

func (p *OIDCProvider) Exchange(
ctx context.Context,
code string,
opts ...oauth2.AuthCodeOption,
) (*oauth2.Token, error) {
return p.Config.Exchange(ctx, code, opts...)
}

// DisplayName returns the public name of the authenticated user.
func (p *OIDCProvider) DisplayName() string {
return p.Name
}

// GetIdentity fetches the identity of the authenticated user from the ID token.
//
// It returns <provider>:<user id>.
func (p *OIDCProvider) GetIdentity(
ctx context.Context,
token *oauth2.Token,
Expand Down
13 changes: 9 additions & 4 deletions database/counter/counter.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package counter handles the logic of a counter.
package counter

import (
Expand All @@ -8,11 +9,13 @@ import (
"github.com/Darkness4/auth-htmx/database"
)

// Repository defines the counter methods.
type Repository interface {
Inc(ctx context.Context, userID string) (new int64, err error)
Get(ctx context.Context, userID string) (int64, error)
}

// NewRepository wraps around a SQL database to execute the counter methods.
func NewRepository(db *sql.DB) Repository {
return &repository{
Queries: database.New(db),
Expand All @@ -23,17 +26,19 @@ type repository struct {
*database.Queries
}

func (r *repository) Inc(ctx context.Context, userID string) (new int64, err error) {
new, err = r.Queries.IncrementCounter(ctx, userID)
// Inc increments the counter of a user in the database by one.
func (r *repository) Inc(ctx context.Context, userID string) (newValue int64, err error) {
newValue, err = r.Queries.IncrementCounter(ctx, userID)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return new, err
return newValue, err
}
if errors.Is(err, sql.ErrNoRows) {
return 1, r.Queries.CreateCounter(ctx, userID)
}
return new, err
return newValue, err
}

// Get the value of the counter of a user from the database.
func (r *repository) Get(ctx context.Context, userID string) (int64, error) {
counter, err := r.Queries.GetCounter(ctx, userID)
if err != nil {
Expand Down
6 changes: 4 additions & 2 deletions database/database.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// The package database handles the methods and definition to manipulate a database.
package database

import (
Expand All @@ -14,6 +15,7 @@ import (
//go:embed migrations/*.sql
var migrations embed.FS

// InitialMigration migrate a sqlite3 database if necessary.
func InitialMigration(db *sql.DB) error {
dbDriver, err := sqlite.WithInstance(db, &sqlite.Config{
NoTxWrap: true,
Expand Down Expand Up @@ -50,10 +52,10 @@ func InitialMigration(db *sql.DB) error {
panic(fmt.Errorf("failed to fetch DB version: %w", err))
} else {
log.Info().Uint("version", version).Msg("DB version detected.")
if new, err := iofsDriver.Next(version); err != nil {
if newVersion, err := iofsDriver.Next(version); err != nil {
log.Info().Uint("version", version).Msg("Latest DB version.")
} else {
log.Warn().Uint("actual", version).Uint("new", new).Msg("New DB version detected.")
log.Warn().Uint("actual", version).Uint("new", newVersion).Msg("New DB version detected.")
}
}
return nil
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ require (
github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/gabriel-vasile/mimetype v1.4.1 // indirect
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/go-stack/stack v1.8.0 // indirect
github.com/goccy/go-json v0.9.11 // indirect
Expand Down Expand Up @@ -174,11 +174,11 @@ require (
golang.org/x/exp v0.0.0-20230724220655-d98519c11495 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.18.0 // indirect
golang.org/x/sync v0.4.0 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/term v0.14.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.14.0 // indirect
golang.org/x/tools v0.15.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/api v0.126.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
Expand All @@ -198,7 +198,7 @@ require (
modernc.org/fileutil v1.2.0 // indirect
modernc.org/golex v1.1.0 // indirect
modernc.org/internal v1.0.0 // indirect
modernc.org/libc v1.30.0 // indirect
modernc.org/libc v1.34.7 // indirect
modernc.org/lldb v1.0.0 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.7.2 // indirect
Expand Down
7 changes: 7 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo=
github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
Expand Down Expand Up @@ -739,6 +741,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down Expand Up @@ -816,6 +819,8 @@ golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down Expand Up @@ -929,6 +934,8 @@ modernc.org/libc v1.28.0 h1:kHB6LtDBV8DEAK7aZT1vWvP92abW9fb8cjb1P9UTpUE=
modernc.org/libc v1.28.0/go.mod h1:DaG/4Q3LRRdqpiLyP0C2m1B8ZMGkQ+cCgOIjEtQlYhQ=
modernc.org/libc v1.30.0 h1:tw+o+UObwSE4Bfu3+Ztz9NW/Olqp7nTL/vcaEY/x4rc=
modernc.org/libc v1.30.0/go.mod h1:SUKVISl2sU6aasM35Y0v4SsSBTt89uDKrvxgXkvsC/4=
modernc.org/libc v1.34.7 h1:VCfLe/1sxA+B+I/LUPXWS27cO+RrdaUixFGUJPZEL/8=
modernc.org/libc v1.34.7/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE=
modernc.org/lldb v1.0.0 h1:6vjDJxQEfhlOLwl4bhpwIz00uyFK4EmSYcbwqwbynsc=
modernc.org/lldb v1.0.0/go.mod h1:jcRvJGWfCGodDZz8BPwiKMJxGJngQ/5DrRapkQnLob8=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
Expand Down
Loading

0 comments on commit b133cf5

Please sign in to comment.