ssso

package module
v0.0.0-...-8877afb Latest Latest
Warning

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

Go to latest
Published: Jan 14, 2025 License: MIT Imports: 21 Imported by: 0

README

Shadow SSO (3SO): Your Go-Powered Identity Fortress 🛡️

A Robust and Flexible OAuth 2.0 and OpenID Connect Implementation for Go

GitHub stars Go Reference License

Shadow SSO provides a complete suite of tools to implement secure authentication and authorization in your Go applications. We've crafted it with clarity and modularity, making it easier to protect your APIs and data. This package is compliant with industry standards, ensuring smooth integration with any client that also adheres to OAuth 2.0 and OIDC principles.

✨ Key Features

Shadow SSO is packed with essential functionality to ensure top-tier security and control over access:

  • ⚙️ Full OAuth 2.0 Support (RFC 6749): Complete implementation covering all necessary protocols, allowing you to manage token lifecycles securely.
  • 🌐 OpenID Connect (OIDC) Support: Secure user identification and profile access using OIDC extensions to OAuth 2.0, bringing trust and interoperability to the table.
  • 🔑 PKCE Support (RFC 7636): Public client security via Proof Key for Code Exchange. This essential addition fortifies against Authorization Code interception threats.
  • 🧐 Token Introspection (RFC 7662): Validate the validity and properties of tokens via a standardized mechanism that doesn't leak crucial information on every request.
  • 🚫 Token Revocation (RFC 7009): Granting immediate cancellation of sessions and ensuring swift response to access threats.
  • 🔑 Session Management: Efficient management of user session state.
  • ✅ Support for Multiple Grant Types:
    • authorization_code - Industry standard for web application login flow.
    • client_credentials - For machine-to-machine authorizations.
    • resource_owner_password - Direct user authorization to protect legacy apps.
    • refresh_token - Seamless re-authentication without re-entering user credentials.
  • 🔒 Secure Token Handling: Ensures sensitive credentials and tokens are stored with encryption where needed, handled with precision, and safeguarded.
  • 👥 Client Application Management: Control registration of clients in order to use and delegate your authentication server.
  • 🕹️ User Session Management: Fine grained access and revocation control over each individual session.

🚀 Getting Started

📦 Installation
go get github.com/pilab-dev/shadow-sso
⚡️ Quick Example

Here's a glimpse of what you need to launch Shadow SSO. Make sure that you fill your implementations for NewYourOAuthRepository() and NewYourUserRepository() methods with logic for persistance using for instance PostgresSQL, MySQL, SQLITE, Redis etc.:

  1. Service Initialization:

    package main
    
    import (
        "github.com/labstack/echo/v4"
        ssso "github.com/pilab-dev/shadow-sso"
        "github.com/pilab-dev/shadow-sso/client"
        "crypto/rsa"
        "log"
    )
    
    func main() {
      // Create a new key
        signingKey, err := ssso.GenerateRSAKey()
        if err != nil {
          log.Fatalf("error generating rsa signing key %s\n", err.Error())
      }
    
        // Initialize repositories
        oauthRepo := NewYourOAuthRepository() // Implement OAuthRepository interface
        userRepo := NewYourUserRepository()    // Implement UserRepository interface
        clientStore := client.NewClientMemoryStore()
    
    
        // Create services
        oauthService := ssso.NewOAuthService(oauthRepo, userRepo, signingKey, "https://your-issuer.com")
        jwksService := ssso.NewJWKSService(signingKey)
        clientService := client.NewClientService(clientStore)
    	    pkceService := ssso.NewPKCEService(oauthRepo)
    
        // Initialize OAuth2 API
        config := ssso.NewDefaultConfig("https://your-issuer.com")
        oauth2API := ssso.NewOAuth2API(
            oauthService,
            jwksService,
            clientService,
            pkceService,
            config,
        )
    
        // Setup Echo server
        e := echo.New()
        oauth2API.RegisterRoutes(e)
        e.Logger.Fatal(e.Start(":8080"))
    }
    
    func loadSigningKey() *rsa.PrivateKey {
        // load RSA from persisted value. Generate otherwise
        key, err := ssso.GenerateRSAKey()
        if err != nil {
        	panic(err)
        }
        return key
    }
    
  2. Client Application Registration:

        client := &ssso.Client{
    	    ID:           "client_id",
    	    Secret:       "client_secret",
    	    Name:         "Example App",
    	    RedirectURIs: []string{"https://example.com/callback"},
    	    GrantTypes:   []string{"authorization_code", "refresh_token"},
    	    Scopes:       []string{"openid", "profile", "email"},
    	    RequirePKCE:  true,
        }
    err := clientService.CreateClient(client)
        if err != nil {
            panic(err)
    }
    
    
  3. Authorization Code Flow:

    import "net/url"
    // 1. Redirect user to authorization endpoint
        authURL := "https://your-issuer.com/oauth2/authorize?" + url.Values{
            "client_id":     {"client_id"},
            "redirect_uri":  {"https://example.com/callback"},
            "response_type": {"code"},
            "scope":         {"openid profile"},
            "state":         {generateRandomState()},
        }.Encode()
    
        // 2. Handle callback and exchange code for tokens
        code := "received_auth_code"
        tokenResponse, err := oauthService.ExchangeAuthorizationCode(
            code,
            "client_id",
            "client_secret",
            "https://example.com/callback",
        )
    
        // now you have access to the tokens `tokenResponse.AccessToken` and others as provided by the implementation of the token generator used in `NewOAuthService` function
    
    
  4. Token Introspection:

        introspection, err := oauthService.IntrospectToken(
            "token_to_inspect",
            "access_token",
            "client_id",
            "client_secret",
        )
    
    if introspection.Active {
            // Token is valid
            userID := introspection.Sub
            scope := introspection.Scope
    }
    
  5. Session Management:

        // List user sessions
        sessions, err := oauthService.GetUserSessions(userID)
    
        // Revoke a session
        err = oauthService.RevokeSession(sessionID)
    
        // Cleanup expired sessions
        err = oauthService.CleanupExpiredSessions(userID)
    
    

🛡️ Security Practices

Our goal with Shadow SSO is not only powerful functionality but, also, unmatched security. For your trust, it comes with these implemented practices:

  • Constant-time Comparisons: For sensitive data (like client secrets or authentication codes) we always use comparison methods that take same time regardless of differences to avoid timing attack possibilities.
  • PKCE by Default: Security is paramount, so public clients are mandated to use PKCE protocol by default, making man-in-the-middle attacks nearly impossible.
  • Secure Token Storage: You have all control and we give all control to ensure encryption when persisting data using repositories implementation, guaranteeing safe storing of all the token, user and client informations.
  • Full-Spectrum Session Management: Our session management approach allows full flexibility when using web and mobile client apps; you can audit user activity and selectively invalidate suspicious ones in response to suspicious requests and/or vulnerabilities discovered.
  • Detailed Token Introspection: Grant granular authorization using our IntrospectToken endpoint for each authorization access request coming from client app for APIs you are in charge to secure.
  • Scope Validation: Each scope requested on the authorize endpoint is validated and unauthorized permissions aren't assigned by our services.
  • Client Authentication: Authenticate any requesting app/client using credentials provided during registration before processing requests with endpoints, giving additional security check.

⚙️ Configuration

Customize Shadow SSO with fine-grained control. You are responsible of what configuration object to pass as configuration to your sso server instance during creation. All the configurable variables are presented in the ssso.OpenIDProviderConfig struct:

    config := &ssso.OpenIDProviderConfig{
    Issuer:                "https://your-issuer.com",
        AuthorizationEndpoint: "https://your-issuer.com/oauth2/authorize",
        TokenEndpoint:         "https://your-issuer.com/oauth2/token",
        UserInfoEndpoint:      "https://your-issuer.com/oauth2/userinfo",
        JwksURI:              "https://your-issuer.com/.well-known/jwks.json",
        // ... additional configuration
    }

	    oauth2API := ssso.NewOAuth2API(
		    oauthService,
		    jwksService,
		    clientService,
		    pkceService,
		    config,
    	)

🧩 Essential Interface Implementation

You’re in the driver's seat on persisting the states. You will need to implement several interfaces. This modular architecture grants the flexibility to incorporate it with your tech stack and specific security standards, if any are required. Implementations stubs are available within the /interfaces module of this repo.

  • OAuthRepository: Interface for persisting data like client registrations, authorization codes, access and refresh tokens, in your preferred method, from standard data store or specific cloud platform solution (check documentation folder for interfaces definition and stub samples).
  • UserRepository: Implements a persistent storage mechanism and manipulation method for sessions associated with a user during usage. (check documentation folder for interfaces definition and stub samples).
  • TokenStore: Implement this in case of memory usage problems and need some form of state management between access token introspection endpoints calls (Optional caching) (check documentation folder for interfaces definition and stub samples).

⚠️ Standardized Error Handling

This package adopts the best practices when reporting errors during processes. In the package /errors directory all the implementation can be found and should be a good starting point for implement your project:

    if err := validateRequest(); err != nil {
	    return errors.NewInvalidRequest("Invalid request parameters")
    }

❤️ Contributing

We appreciate any form of contribution! Please take time to follow the rules on the official guidelines, you are always welcomed: https://github.com/pilab-dev/shadow-sso/blob/main/.github/CONTRIBUTING.md.

📜 License

Shadow SSO is released under the MIT License, giving you full freedom on utilizing, sharing, changing, and distributing with all other parties (check license files for all the details).

Contact 📞

If any doubt, send a direct email message to gyula@pilab.hu or join our public Discord channel by requesting invite on same email.


This updated README provides a clearer structure, utilizes visuals, and offers a more comprehensive explanation of Shadow SSO's features, usage, and security considerations. It's designed to be more engaging and helpful for potential users and contributors.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidConfig = errors.New("invalid configuration")

Functions

func GenerateRSAKey

func GenerateRSAKey() (*rsa.PrivateKey, error)

GenerateRSAKey generates a new RSA private key. It returns the key and any error that occurred during the generation process.

func HashToken

func HashToken(token string) string

func ValidatePKCEChallenge

func ValidatePKCEChallenge(challenge, verifier string) bool

ValidatePKCEChallenge validates a code verifier against a code challenge

Types

type AuthCode

type AuthCode struct {
	Code        string    `json:"code"`         // Unique authorization code
	ClientID    string    `json:"client_id"`    // Client application ID
	UserID      string    `json:"user_id"`      // User who authorized the request
	RedirectURI string    `json:"redirect_uri"` // Client's callback URL
	Scope       string    `json:"scope"`        // Authorized scopes
	ExpiresAt   time.Time `json:"expires_at"`   // Expiration timestamp
	Used        bool      `json:"used"`         // Whether code has been exchanged
	CreatedAt   time.Time `json:"created_at"`   // Creation timestamp

	CodeChallenge       string `json:"code_challenge,omitempty"`
	CodeChallengeMethod string `json:"code_challenge_method,omitempty"`
}

AuthCode represents an OAuth 2.0 authorization code

type AuthorizeRequest

type AuthorizeRequest struct {
	ClientID     string
	RedirectURI  string
	ResponseType string
	Scope        string
	State        string
}

AuthorizeRequest represents an OAuth 2.0 authorization request

type ClaimsConfig

type ClaimsConfig struct {
	SupportedClaims       []string          `json:"supported_claims"`
	SupportedScopes       []string          `json:"supported_scopes"`
	ClaimsMappings        map[string]string `json:"claims_mappings"`
	EnableClaimsParameter bool              `json:"enable_claims_parameter"`
}

ClaimsConfig contains claims-related settings

type Client

type Client struct {
	ID           string    `json:"id"`            // Unique client identifier
	Secret       string    `json:"-"`             // Client secret (hashed)
	Name         string    `json:"name"`          // Client application name
	RedirectURIs []string  `json:"redirect_uris"` // Allowed redirect URIs
	GrantTypes   []string  `json:"grant_types"`   // Allowed grant types
	Scopes       []string  `json:"scopes"`        // Allowed scopes
	CreatedAt    time.Time `json:"created_at"`    // Creation timestamp
	UpdatedAt    time.Time `json:"updated_at"`    // Last update timestamp
}

Client represents an OAuth 2.0 client application

type EndpointConfig

type EndpointConfig struct {
	Authorization bool `json:"authorization"`
	Token         bool `json:"token"`
	UserInfo      bool `json:"userinfo"`
	JWKS          bool `json:"jwks"`
	Registration  bool `json:"registration"`
	Revocation    bool `json:"revocation"`
	Introspection bool `json:"introspection"`
	EndSession    bool `json:"end_session"`
}

EndpointConfig controls which endpoints are enabled

type FlowConfig

type FlowConfig struct {
	AuthorizationCode bool `json:"authorization_code"`
	Implicit          bool `json:"implicit"`
	Hybrid            bool `json:"hybrid"`
}

FlowConfig controls which OAuth2/OIDC flows are enabled

type GrantTypesConfig

type GrantTypesConfig struct {
	AuthorizationCode bool `json:"authorization_code"`
	ClientCredentials bool `json:"client_credentials"`
	RefreshToken      bool `json:"refresh_token"`
	Password          bool `json:"password"`
	Implicit          bool `json:"implicit"`
	JWTBearer         bool `json:"jwt_bearer"`
	DeviceCode        bool `json:"device_code"`
}

GrantTypesConfig controls which grant types are enabled

type JSONWebKey

type JSONWebKey struct {
	Kid string `json:"kid"`
	Kty string `json:"kty"`
	Alg string `json:"alg"`
	Use string `json:"use"`
	N   string `json:"n"`
	E   string `json:"e"`
}

type JSONWebKeySet

type JSONWebKeySet struct {
	Keys []JSONWebKey `json:"keys"`
}

type JWK

type JWK struct {
	Kid string `json:"kid"`
	Kty string `json:"kty"`
	Alg string `json:"alg"`
	Use string `json:"use"`
	N   string `json:"n"`
	E   string `json:"e"`
}

type JWKS

type JWKS struct {
	Keys []JWK `json:"keys"`
}

type JWKSService

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

func NewJWKSService

func NewJWKSService(keyRotation time.Duration) (*JWKSService, error)

func (*JWKSService) GetJWKS

func (s *JWKSService) GetJWKS() JSONWebKeySet

func (*JWKSService) GetSigningKey

func (s *JWKSService) GetSigningKey() (string, *rsa.PrivateKey)

type OAuth2API

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

OAuth2API struct to hold dependencies

func NewOAuth2API

func NewOAuth2API(
	service *OAuthService,
	jwksService *JWKSService,
	clientService *client.ClientService,
	pkceService *PKCEService,
	config *OpenIDProviderConfig,
) *OAuth2API

NewOAuth2API initializes the OAuth2 API

func (*OAuth2API) AuthorizeHandler

func (api *OAuth2API) AuthorizeHandler(c echo.Context) error

AuthorizeHandler handles OAuth 2.0 authorization requests. It validates the client, redirect URI, response type, scope, and PKCE (Proof Key for Code Exchange) requirements. If all validations pass, it generates an authorization code and redirects the user to the provided redirect URI with the code.

func (*OAuth2API) ClientCredentialsHandler

func (api *OAuth2API) ClientCredentialsHandler(c echo.Context) error

ClientCredentialsHandler handles the Client Credentials flow

func (*OAuth2API) DirectGrantHandler

func (api *OAuth2API) DirectGrantHandler(c echo.Context) error

DirectGrantHandler handles the Resource Owner Password Credentials flow

func (*OAuth2API) IntrospectHandler

func (api *OAuth2API) IntrospectHandler(c echo.Context) error

IntrospectHandler implements RFC 7662 Token Introspection. It checks for required parameters (client_id, client_secret, and token), authenticates the client, and then calls the IntrospectToken method to inspect the token. If the introspection fails, it returns a 200 OK response with active=false as per the RFC. Otherwise, it returns the introspection result.

func (*OAuth2API) JWKSHandler

func (api *OAuth2API) JWKSHandler(c echo.Context) error

func (*OAuth2API) OpenIDConfigurationHandler

func (api *OAuth2API) OpenIDConfigurationHandler(c echo.Context) error

func (*OAuth2API) RegisterRoutes

func (api *OAuth2API) RegisterRoutes(e *echo.Echo)

RegisterRoutes registers the OAuth2 routes

func (*OAuth2API) RevokeHandler

func (api *OAuth2API) RevokeHandler(c echo.Context) error

RevokeHandler handles token revocation requests according to RFC 7009. It accepts both access tokens and refresh tokens and revokes them. The endpoint always returns 200 OK regardless of whether the token was successfully revoked or not.

func (*OAuth2API) TokenHandler

func (api *OAuth2API) TokenHandler(c echo.Context) error

TokenHandler handles OAuth2 token requests. It:

  • Extracts client_id, client_secret, and grant_type from the request form values.
  • Validates the client credentials and grant type.
  • Processes the grant type by calling one of three handler functions based on the grant type (authorization_code, refresh_token, or client_credentials).
  • Returns a JSON response with the token response if successful, or an error response if any of the validation or processing steps fail.

func (*OAuth2API) UserInfoHandler

func (api *OAuth2API) UserInfoHandler(c echo.Context) error

UserInfoHandler handles HTTP requests to retrieve user information. It expects an "Authorization" header with a Bearer token, validates the token, and returns the associated user information if valid. If the token is missing, invalid, or cannot be validated, it returns a JSON error response with a 401 Unauthorized status code.

type OAuthRepository

type OAuthRepository interface {
	io.Closer

	// CreateClient creates a new OAuth client in the repository.
	// Returns an error if the client already exists or if there's a database error.
	CreateClient(ctx context.Context, client *Client) error

	// GetClient retrieves a client by its client ID.
	// Returns the client if found, or an error if not found or if there's a database error.
	GetClient(ctx context.Context, clientID string) (*Client, error)

	// ValidateClient verifies if the provided client credentials (ID and secret) are valid.
	// Returns nil if valid, or an error if invalid credentials or database error.
	ValidateClient(ctx context.Context, clientID, clientSecret string) error

	// UpdateClient updates an existing OAuth client's information.
	// Returns an error if the client doesn't exist or if there's a database error.
	UpdateClient(ctx context.Context, client *Client) error

	// DeleteClient removes a client and all associated data from the repository.
	// Returns an error if the client doesn't exist or if there's a database error.
	DeleteClient(ctx context.Context, clientID string) error

	// SaveAuthCode stores a new authorization code in the repository.
	// Returns an error if the code already exists or if there's a database error.
	SaveAuthCode(ctx context.Context, code *AuthCode) error

	// GetAuthCode retrieves an authorization code by its value.
	// Returns the authorization code if found, or an error if not found or database error.
	GetAuthCode(ctx context.Context, code string) (*AuthCode, error)

	// MarkAuthCodeAsUsed marks an authorization code as used to prevent replay attacks.
	// Returns an error if the code doesn't exist or if there's a database error.
	MarkAuthCodeAsUsed(ctx context.Context, code string) error

	// DeleteExpiredAuthCodes removes all expired authorization codes from the repository.
	// Returns an error if there's a database error during cleanup.
	DeleteExpiredAuthCodes(ctx context.Context) error

	// StoreToken saves a new access or refresh token in the repository.
	// Returns an error if the token already exists or if there's a database error.
	StoreToken(ctx context.Context, token *Token) error

	// GetAccessToken retrieves an access token by its value.
	// Returns the token if found, or an error if not found or database error.
	GetAccessToken(ctx context.Context, tokenValue string) (*Token, error)

	// GetRefreshToken retrieves a refresh token by its value.
	// Returns the token if found, or an error if not found or database error.
	GetRefreshToken(ctx context.Context, tokenValue string) (*Token, error)

	// GetRefreshTokenInfo retrieves metadata about a refresh token.
	// Returns the token info if found, or an error if not found or database error.
	GetRefreshTokenInfo(ctx context.Context, tokenValue string) (*TokenInfo, error)

	// GetAccessTokenInfo retrieves metadata about an access token.
	// Returns the token info if found, or an error if not found or database error.
	GetAccessTokenInfo(ctx context.Context, tokenValue string) (*TokenInfo, error)

	// RevokeToken invalidates an access token.
	// Returns an error if the token doesn't exist or if there's a database error.
	RevokeToken(ctx context.Context, tokenValue string) error

	// RevokeRefreshToken invalidates a refresh token.
	// Returns an error if the token doesn't exist or if there's a database error.
	RevokeRefreshToken(ctx context.Context, tokenValue string) error

	// RevokeAllUserTokens invalidates all tokens associated with a user.
	// Returns an error if there's a database error during revocation.
	RevokeAllUserTokens(ctx context.Context, userID string) error

	// RevokeAllClientTokens invalidates all tokens associated with a client.
	// Returns an error if there's a database error during revocation.
	RevokeAllClientTokens(ctx context.Context, clientID string) error

	// DeleteExpiredTokens removes all expired tokens from the repository.
	// Returns an error if there's a database error during cleanup.
	DeleteExpiredTokens(ctx context.Context) error

	// ValidateAccessToken verifies if an access token is valid and returns the associated user ID.
	// Returns the user ID if valid, or an error if invalid or database error.
	ValidateAccessToken(ctx context.Context, token string) (string, error)

	// GetTokenInfo retrieves detailed information about a token as per RFC 7662.
	// Returns the token information if found, or an error if not found or database error.
	GetTokenInfo(ctx context.Context, tokenValue string) (*Token, error)

	// CreateSession creates a new user session.
	// Returns an error if the session already exists or if there's a database error.
	CreateSession(ctx context.Context, userID string, session *UserSession) error

	// GetUserSessions retrieves all active sessions for a user.
	// Returns a slice of sessions if found, or an error if not found or database error.
	GetUserSessions(ctx context.Context, userID string) ([]UserSession, error)

	// GetSessionByToken retrieves a session by its associated token.
	// Returns the session if found, or an error if not found or database error.
	GetSessionByToken(ctx context.Context, token string) (*UserSession, error)

	// UpdateSessionLastUsed updates the last used timestamp of a session.
	// Returns an error if the session doesn't exist or if there's a database error.
	UpdateSessionLastUsed(ctx context.Context, sessionID string) error

	// RevokeSession invalidates a specific session.
	// Returns an error if the session doesn't exist or if there's a database error.
	RevokeSession(ctx context.Context, sessionID string) error

	// DeleteExpiredSessions removes all expired sessions for a user.
	// Returns an error if there's a database error during cleanup.
	DeleteExpiredSessions(ctx context.Context, userID string) error

	// SaveCodeChallenge stores a PKCE code challenge for a given authorization code.
	// Returns an error if the challenge already exists or if there's a database error.
	SaveCodeChallenge(ctx context.Context, code, challenge string) error

	// GetCodeChallenge retrieves a PKCE code challenge for verification.
	// Returns the challenge if found, or an error if not found or database error.
	GetCodeChallenge(ctx context.Context, code string) (string, error)

	// DeleteCodeChallenge removes a PKCE code challenge after use.
	// Returns an error if the challenge doesn't exist or if there's a database error.
	DeleteCodeChallenge(ctx context.Context, code string) error
}

OAuthRepository defines the interface for OAuth 2.0 data operations. This interface provides a comprehensive set of methods to manage OAuth 2.0 entities including clients, authorization codes, tokens, sessions, and PKCE challenges.

type OAuthService

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

func NewOAuthService

func NewOAuthService(oauthRepo OAuthRepository, userRepo UserRepository, signingKey *rsa.PrivateKey, issuer string) *OAuthService

func (*OAuthService) CleanupExpiredSessions

func (s *OAuthService) CleanupExpiredSessions(ctx context.Context, userID string) error

Lejárt session-ök törlése

func (*OAuthService) ClientCredentials

func (s *OAuthService) ClientCredentials(ctx context.Context, clientID, clientSecret, scope string) (*TokenResponse, error)

ClientCredentials implements the Client Credentials flow

func (*OAuthService) ClientCredentialsGrant

func (s *OAuthService) ClientCredentialsGrant(ctx context.Context, clientID, clientSecret, scope string) (*TokenResponse, error)

func (*OAuthService) DirectGrant

func (s *OAuthService) DirectGrant(ctx context.Context, clientID, clientSecret, username, password, scope string) (*TokenResponse, error)

DirectGrant implements the Resource Owner Password Credentials flow

func (*OAuthService) ExchangeAuthorizationCode

func (s *OAuthService) ExchangeAuthorizationCode(ctx context.Context, code, clientID, clientSecret, redirectURI string) (*TokenResponse, error)

func (*OAuthService) GenerateAuthCode

func (s *OAuthService) GenerateAuthCode(ctx context.Context, clientID, redirectURI, scope string) (string, error)

GenerateAuthCode generates a new authorization code for OAuth2 authorization code flow. It creates a secure random code and stores it with the provided client details.

func (*OAuthService) GenerateTokens

func (s *OAuthService) GenerateTokens(ctx context.Context, code, clientID string) (*TokenResponse, error)

GenerateTokens exchanges an authorization code for access and refresh tokens. It validates the code and client ID before generating new tokens.

func (*OAuthService) GetJWKS

func (s *OAuthService) GetJWKS() JWKS

func (*OAuthService) GetUserInfo

func (s *OAuthService) GetUserInfo(ctx context.Context, token string) (map[string]interface{}, error)

GetUserInfo retrieves user information for a valid access token.

func (*OAuthService) GetUserSessions

func (s *OAuthService) GetUserSessions(ctx context.Context, userID string) ([]UserSession, error)

Új metódus a felhasználó session-jeinek lekérdezéséhez

func (*OAuthService) IntrospectToken

func (s *OAuthService) IntrospectToken(ctx context.Context, token, tokenTypeHint, clientID, clientSecret string) (*TokenIntrospection, error)

IntrospectToken implements RFC 7662 Token Introspection

func (*OAuthService) Login

func (s *OAuthService) Login(ctx context.Context, username, password, deviceInfo string) (*TokenResponse, error)

func (*OAuthService) PasswordGrant

func (s *OAuthService) PasswordGrant(ctx context.Context, username, password, scope string, cli *client.Client) (*TokenResponse, error)

func (*OAuthService) RefreshToken

func (s *OAuthService) RefreshToken(ctx context.Context, refreshToken string, clientID string) (*TokenResponse, error)

Token frissítése

func (*OAuthService) RegisterUser

func (s *OAuthService) RegisterUser(ctx context.Context, username, password string) (*User, error)

func (*OAuthService) RevokeSession

func (s *OAuthService) RevokeSession(ctx context.Context, sessionID string) error

Session visszavonása (kijelentkezés)

func (*OAuthService) RevokeToken

func (s *OAuthService) RevokeToken(ctx context.Context, token string) error

RevokeToken revokes an access token.

func (*OAuthService) ValidateClient

func (s *OAuthService) ValidateClient(ctx context.Context, clientID, clientSecret string) (*Client, error)

Additional methods for OAuthService

func (*OAuthService) ValidateToken

func (s *OAuthService) ValidateToken(ctx context.Context, token string) (string, error)

ValidateToken validates an access token and returns the associated user ID.

type OpenIDConfiguration

type OpenIDConfiguration struct {
	Issuer                                    string   `json:"issuer"`
	AuthorizationEndpoint                     string   `json:"authorization_endpoint"`
	TokenEndpoint                             string   `json:"token_endpoint"`
	UserInfoEndpoint                          string   `json:"userinfo_endpoint"`
	JwksURI                                   string   `json:"jwks_uri"`
	RegistrationEndpoint                      *string  `json:"registration_endpoint,omitempty"`
	ScopesSupported                           []string `json:"scopes_supported"`
	ResponseTypesSupported                    []string `json:"response_types_supported"`
	ResponseModesSupported                    []string `json:"response_modes_supported"`
	GrantTypesSupported                       []string `json:"grant_types_supported"`
	TokenEndpointAuthMethodsSupported         []string `json:"token_endpoint_auth_methods_supported"`
	TokenEndpointAuthSigningAlgSupported      []string `json:"token_endpoint_auth_signing_alg_values_supported,omitempty"`
	ServiceDocumentation                      *string  `json:"service_documentation,omitempty"`
	UILocalesSupported                        []string `json:"ui_locales_supported,omitempty"`
	OpPolicyURI                               *string  `json:"op_policy_uri,omitempty"`
	OpTosURI                                  *string  `json:"op_tos_uri,omitempty"`
	RevocationEndpoint                        *string  `json:"revocation_endpoint,omitempty"`
	RevocationEndpointAuthMethodsSupported    []string `json:"revocation_endpoint_auth_methods_supported,omitempty"`
	IntrospectionEndpoint                     *string  `json:"introspection_endpoint,omitempty"`
	IntrospectionEndpointAuthMethodsSupported []string `json:"introspection_endpoint_auth_methods_supported,omitempty"`
	CodeChallengeMethodsSupported             []string `json:"code_challenge_methods_supported,omitempty"`
	SubjectTypesSupported                     []string `json:"subject_types_supported"`
	IDTokenSigningAlgValuesSupported          []string `json:"id_token_signing_alg_values_supported"`
	IDTokenEncryptionAlgValuesSupported       []string `json:"id_token_encryption_alg_values_supported,omitempty"`
	IDTokenEncryptionEncValuesSupported       []string `json:"id_token_encryption_enc_values_supported,omitempty"`
	UserinfoSigningAlgValuesSupported         []string `json:"userinfo_signing_alg_values_supported,omitempty"`
	UserinfoEncryptionAlgValuesSupported      []string `json:"userinfo_encryption_alg_values_supported,omitempty"`
	UserinfoEncryptionEncValuesSupported      []string `json:"userinfo_encryption_enc_values_supported,omitempty"`
	RequestObjectSigningAlgValuesSupported    []string `json:"request_object_signing_alg_values_supported,omitempty"`
	RequestObjectEncryptionAlgValuesSupported []string `json:"request_object_encryption_alg_values_supported,omitempty"`
	RequestObjectEncryptionEncValuesSupported []string `json:"request_object_encryption_enc_values_supported,omitempty"`
	ClaimsSupported                           []string `json:"claims_supported,omitempty"`
	ClaimsParameterSupported                  bool     `json:"claims_parameter_supported"`
	RequestParameterSupported                 bool     `json:"request_parameter_supported"`
	RequestURIParameterSupported              bool     `json:"request_uri_parameter_supported"`
	RequireRequestURIRegistration             bool     `json:"require_request_uri_registration"`
}

OpenIDConfiguration represents the OpenID Connect discovery document

type OpenIDProviderConfig

type OpenIDProviderConfig struct {
	// Basic Settings
	Issuer            string        `json:"issuer"`
	AccessTokenTTL    time.Duration `json:"access_token_ttl"`
	RefreshTokenTTL   time.Duration `json:"refresh_token_ttl"`
	AuthCodeTTL       time.Duration `json:"auth_code_ttl"`
	IDTokenTTL        time.Duration `json:"id_token_ttl"`
	SessionTTL        time.Duration `json:"session_ttl"`
	KeyRotationPeriod time.Duration `json:"key_rotation_period"`
	RequireConsent    bool          `json:"require_consent"`
	ForceConsent      bool          `json:"force_consent"`

	// Endpoint Configuration
	EnabledEndpoints EndpointConfig `json:"enabled_endpoints"`

	// Flow Configuration
	EnabledFlows FlowConfig `json:"enabled_flows"`

	// Grant Types Configuration
	EnabledGrantTypes GrantTypesConfig `json:"enabled_grant_types"`

	// Security Configuration
	SecurityConfig SecurityConfig `json:"security_config"`

	// Token Configuration
	TokenConfig TokenConfig `json:"token_config"`

	// PKCE Configuration
	PKCEConfig PKCEConfig `json:"pkce_config"`

	// Claims Configuration
	ClaimsConfig ClaimsConfig `json:"claims_config"`
}

OpenIDProviderConfig represents the complete configuration for the OpenID Connect provider

func NewDefaultConfig

func NewDefaultConfig(issuer string) *OpenIDProviderConfig

NewDefaultConfig creates a new OpenIDProviderConfig with sensible defaults.

func (*OpenIDProviderConfig) IsEndpointEnabled

func (c *OpenIDProviderConfig) IsEndpointEnabled(endpoint string) bool

IsEndpointEnabled checks if a specific endpoint is enabled

func (*OpenIDProviderConfig) IsGrantTypeEnabled

func (c *OpenIDProviderConfig) IsGrantTypeEnabled(grantType string) bool

IsGrantTypeEnabled checks if a specific grant type is enabled

func (*OpenIDProviderConfig) Validate

func (c *OpenIDProviderConfig) Validate() error

Validate checks if the configuration is valid

type PKCEConfig

type PKCEConfig struct {
	Enabled                   bool     `json:"enabled"`
	AllowPlainChallengeMethod bool     `json:"allow_plain_challenge_method"`
	SupportedMethods          []string `json:"supported_methods"`
}

PKCEConfig contains PKCE-related settings

type PKCEParams

type PKCEParams struct {
	CodeChallenge       string
	CodeChallengeMethod string
}

PKCEParams represents PKCE parameters

type PKCEService

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

PKCEService handles PKCE validation

func NewPKCEService

func NewPKCEService(oauthRepo OAuthRepository) *PKCEService

NewPKCEService creates a new PKCE service instance

func (*PKCEService) SavePKCEChallenge

func (s *PKCEService) SavePKCEChallenge(ctx context.Context, code, challenge string) error

func (*PKCEService) ValidateCodeVerifier

func (s *PKCEService) ValidateCodeVerifier(ctx context.Context, code, verifier string) error

ValidateCodeVerifier validates the PKCE code verifier against the stored challenge

func (*PKCEService) ValidatePKCE

func (s *PKCEService) ValidatePKCE(ctx context.Context, code string, codeVerifier string) error

ValidatePKCE validates the PKCE code verifier against the stored code challenge code: The authorization code to validate codeVerifier: The PKCE code verifier provided by the client Returns error if validation fails

type SecurityConfig

type SecurityConfig struct {
	RequirePKCE                   bool     `json:"require_pkce"`
	RequirePKCEForPublicClients   bool     `json:"require_pkce_for_public_clients"`
	AllowedSigningAlgs            []string `json:"allowed_signing_algs"`
	AllowedEncryptionAlgs         []string `json:"allowed_encryption_algs"`
	AllowedEncryptionEnc          []string `json:"allowed_encryption_enc"`
	RequireSignedRequestObject    bool     `json:"require_signed_request_object"`
	RequireRequestURIRegistration bool     `json:"require_request_uri_registration"`
	DefaultMaxAge                 int      `json:"default_max_age"`
	RequireAuthTime               bool     `json:"require_auth_time"`
}

SecurityConfig contains security-related settings

type Token

type Token struct {
	ID         string    `json:"id"`           // Unique token identifier
	TokenType  string    `json:"token_type"`   // "access_token" or "refresh_token"
	TokenValue string    `json:"token_value"`  // The actual token string
	ClientID   string    `json:"client_id"`    // Client that requested the token
	UserID     string    `json:"user_id"`      // User who authorized the token
	Scope      string    `json:"scope"`        // Authorized scopes
	ExpiresAt  time.Time `json:"expires_at"`   // Expiration timestamp
	IsRevoked  bool      `json:"is_revoked"`   // Whether token is revoked
	CreatedAt  time.Time `json:"created_at"`   // Creation timestamp
	LastUsedAt time.Time `json:"last_used_at"` // Last usage timestamp
}

Token represents an OAuth 2.0 token (access or refresh)

type TokenConfig

type TokenConfig struct {
	AccessTokenFormat          string   `json:"access_token_format"` // JWT or opaque
	IDTokenSigningAlg          string   `json:"id_token_signing_alg"`
	AccessTokenSigningAlg      string   `json:"access_token_signing_alg"`
	SupportedResponseTypes     []string `json:"supported_response_types"`
	SupportedResponseModes     []string `json:"supported_response_modes"`
	SupportedTokenEndpointAuth []string `json:"supported_token_endpoint_auth"`
}

TokenConfig contains token-related settings

type TokenInfo

type TokenInfo struct {
	ID        string    `json:"id"`         // Unique token identifier
	TokenType string    `json:"token_type"` // "access_token" or "refresh_token"
	ClientID  string    `json:"client_id"`  // Client that the token was issued to
	UserID    string    `json:"user_id"`    // User that authorized the token
	Scope     string    `json:"scope"`      // Authorized scopes
	IssuedAt  time.Time `json:"issued_at"`  // When the token was issued
	ExpiresAt time.Time `json:"expires_at"` // When the token expires
	IsRevoked bool      `json:"is_revoked"` // Whether token has been revoked
}

TokenInfo represents metadata about a token

type TokenIntrospection

type TokenIntrospection struct {
	Active    bool   `json:"active"`
	Scope     string `json:"scope,omitempty"`
	ClientID  string `json:"client_id,omitempty"`
	Username  string `json:"username,omitempty"`
	TokenType string `json:"token_type,omitempty"`
	Exp       int64  `json:"exp,omitempty"`
	Iat       int64  `json:"iat,omitempty"`
	Nbf       int64  `json:"nbf,omitempty"`
	Sub       string `json:"sub,omitempty"`
	Aud       string `json:"aud,omitempty"`
	Iss       string `json:"iss,omitempty"`
	Jti       string `json:"jti,omitempty"`
}

TokenIntrospection represents the response format defined in RFC 7662

type TokenRequest

type TokenRequest struct {
	GrantType    string
	Code         string
	RedirectURI  string
	ClientID     string
	ClientSecret string
	RefreshToken string
}

TokenRequest represents an OAuth 2.0 token request

type TokenResponse

type TokenResponse struct {
	AccessToken  string `json:"access_token"`
	TokenType    string `json:"token_type"`
	ExpiresIn    int    `json:"expires_in"`
	RefreshToken string `json:"refresh_token,omitempty"`
	Scope        string `json:"scope,omitempty"`
}

TokenResponse represents an OAuth 2.0 token response

type TokenService

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

TokenService handles token generation and validation

func NewTokenService

func NewTokenService(repo OAuthRepository, cache TokenStore, issuer string, tokenTTL time.Duration) *TokenService

NewTokenService creates a new TokenService instance

func (*TokenService) GenerateTokenPair

func (s *TokenService) GenerateTokenPair(ctx context.Context, clientID, userID, scope string) (*TokenResponse, error)

GenerateTokenPair creates a new access and refresh token pair

func (*TokenService) ValidateToken

func (s *TokenService) ValidateToken(ctx context.Context, tokenValue string) (*Token, error)

ValidateToken validates an access token and returns its information

type TokenStore

type TokenStore interface {
	// Close closes the token store.
	io.Closer

	// Set stores a token in the cache.
	// Returns an error if the operation fails.
	Set(ctx context.Context, token *Token) error

	// Get retrieves a token from the cache by its value.
	// Returns the token and true if found, or nil and false if not found.
	Get(ctx context.Context, tokenValue string) (*Token, bool)

	// Delete removes a token from the cache.
	// Returns an error if the operation fails.
	Delete(ctx context.Context, tokenValue string) error

	// Clear removes all tokens from the cache.
	// Returns an error if the operation fails.
	Clear(ctx context.Context) error

	// DeleteExpired removes all expired tokens from the cache.
	// Returns an error if the operation fails.
	DeleteExpired(ctx context.Context) error

	// Count returns the number of tokens currently in the cache.
	Count(ctx context.Context) int
}

TokenStore represents the interface for token caching operations. This interface provides methods to manage a temporary token cache for improved performance.

type User

type User struct {
	// Unique identifier for the user
	ID string
	// Username used for authentication
	Username string
	// Hashed password for authentication
	Password string
	// Time when the user account was created
	CreatedAt time.Time
	// Time when the user account was last updated
	UpdatedAt time.Time
}

User represents a registered user in the system

type UserRepository

type UserRepository interface {
	// CreateUser creates a new user with the given username and password
	// Returns the created user or an error if creation fails
	CreateUser(ctx context.Context, username, password string) (*User, error)

	// GetUserByID retrieves a user by their unique ID
	// Returns the user or an error if not found
	GetUserByID(ctx context.Context, id string) (*User, error)

	// GetUserByUsername retrieves a user by their username
	// Returns the user or an error if not found
	GetUserByUsername(ctx context.Context, username string) (*User, error)

	// UpdateUser updates an existing user's information
	// Returns an error if the update fails
	UpdateUser(ctx context.Context, user *User) error

	// DeleteUser removes a user by their ID
	// Returns an error if deletion fails
	DeleteUser(ctx context.Context, id string) error

	// CreateSession creates a new session for the given user
	// Returns an error if session creation fails
	CreateSession(ctx context.Context, userID string, session *UserSession) error

	// GetUserSessions retrieves all active sessions for a user
	// Returns a slice of sessions or an error if retrieval fails
	GetUserSessions(ctx context.Context, userID string) ([]UserSession, error)

	// GetSessionByToken retrieves a session by its access token
	// Returns the session or an error if not found
	GetSessionByToken(ctx context.Context, accessToken string) (*UserSession, error)

	// UpdateSessionLastUsed updates the LastUsedAt timestamp of a session
	// Returns an error if the update fails
	UpdateSessionLastUsed(ctx context.Context, sessionID string) error

	// RevokeSession marks a session as revoked
	// Returns an error if the revocation fails
	RevokeSession(ctx context.Context, sessionID string) error

	// DeleteExpiredSessions removes all expired sessions for a user
	// Returns an error if the deletion fails
	DeleteExpiredSessions(ctx context.Context, userID string) error
}

UserRepository defines the interface for user-related data operations

type UserSession

type UserSession struct {
	ID           string    `json:"id"`            // Unique session identifier
	UserID       string    `json:"user_id"`       // User ID
	AccessToken  string    `json:"access_token"`  // Current access token
	RefreshToken string    `json:"refresh_token"` // Current refresh token
	ExpiresAt    time.Time `json:"expires_at"`    // Session expiration
	CreatedAt    time.Time `json:"created_at"`    // When session was created
	LastUsedAt   time.Time `json:"last_used_at"`  // Last activity timestamp
	DeviceInfo   string    `json:"device_info"`   // Client device information
	IsRevoked    bool      `json:"is_revoked"`    // Whether session is revoked
}

UserSession represents a user's login session

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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