### Build and Run OAuth2 Server Source: https://github.com/go-oauth2/oauth2/blob/master/example/README.md Navigate to the server example directory, build the executable, and run the server. ```bash cd example/server go build server.go ./server ``` -------------------------------- ### Build and Run OAuth2 Client Source: https://github.com/go-oauth2/oauth2/blob/master/example/README.md Navigate to the client example directory, build the executable, and run the client. ```bash cd example/client go build client.go ./client ``` -------------------------------- ### Install OAuth 2.0 Package Source: https://github.com/go-oauth2/oauth2/blob/master/README.md Download and install the Go OAuth 2.0 package using the go get command. ```bash go get -u -v github.com/go-oauth2/oauth2/v4/... ``` -------------------------------- ### Build and Run Server Source: https://github.com/go-oauth2/oauth2/blob/master/README.md Compile the Go server file and then run the executable to start the OAuth 2.0 server. ```bash go build server.go ./server ``` -------------------------------- ### Client Credentials Grant Flow Example Source: https://context7.com/go-oauth2/oauth2/llms.txt Demonstrates how to obtain an access token using client credentials, suitable for machine-to-machine authentication. Supports POST requests and GET requests if AllowGetAccessRequest is enabled. ```curl curl -X POST http://localhost:9096/token \ -d "grant_type=client_credentials" \ -d "client_id=my-client-id" \ -d "client_secret=my-client-secret" \ -d "scope=read" ``` ```json { "access_token": "OA6ITALNMDOGD58C0SN-MG", "token_type": "Bearer", "expires_in": 7200, "scope": "read" } ``` ```http GET http://localhost:9096/token?grant_type=client_credentials&client_id=my-client-id&client_secret=my-client-secret&scope=read ``` -------------------------------- ### Client Request with Bearer Token Source: https://context7.com/go-oauth2/oauth2/llms.txt Example using curl to make a request to a protected resource, including the Authorization header with a bearer token. ```bash # Client request with bearer token # curl -H "Authorization: Bearer J86XVRYSNFCFI233KXDL0Q" http://localhost:9096/api/resource ``` -------------------------------- ### Token Response Example Source: https://github.com/go-oauth2/oauth2/blob/master/README.md A sample JSON response received after a successful token request, containing the access token, expiration time, scope, and token type. ```json { "access_token": "J86XVRYSNFCFI233KXDL0Q", "expires_in": 7200, "scope": "read", "token_type": "Bearer" } ``` -------------------------------- ### Authorization Request URL Source: https://github.com/go-oauth2/oauth2/blob/master/README.md Example URL to initiate an authorization code grant flow. Ensure the client_id and response_type parameters are correctly set. ```http http://localhost:9096/authorize?client_id=000000&response_type=code ``` -------------------------------- ### Grant Token Request URL Source: https://github.com/go-oauth2/oauth2/blob/master/README.md Example URL to request an access token using client credentials. Includes grant_type, client_id, client_secret, and scope. ```http http://localhost:9096/token?grant_type=client_credentials&client_id=000000&client_secret=999999&scope=read ``` -------------------------------- ### Authorization Code Grant Flow Example Source: https://context7.com/go-oauth2/oauth2/llms.txt Illustrates the steps for the Authorization Code Grant flow, including the initial authorization request, user redirection, and exchanging the code for tokens. This is a common flow for web applications. ```http GET http://localhost:9096/authorize?client_id=my-client-id&response_type=code&redirect_uri=http://localhost:8080/callback&scope=read&state=xyz ``` ```http http://localhost:8080/callback?code=AUTHORIZATION_CODE&state=xyz ``` ```curl curl -X POST http://localhost:9096/token \ -d "grant_type=authorization_code" \ -d "code=AUTHORIZATION_CODE" \ -d "client_id=my-client-id" \ -d "client_secret=my-client-secret" \ -d "redirect_uri=http://localhost:8080/callback" ``` ```json { "access_token": "J86XVRYSNFCFI233KXDL0Q", "token_type": "Bearer", "refresh_token": "5FBLXQ47XJ2MGTY8YRZQ8W", "expires_in": 7200 } ``` -------------------------------- ### Request Token with Password Grant Source: https://context7.com/go-oauth2/oauth2/llms.txt Example using curl to request an access token using the password grant type. This requires sending user credentials directly. ```bash # Request token using password grant # curl -X POST http://localhost:9096/token \ # -d "grant_type=password" \ # -d "username=test" \ # -d "password=test" \ # -d "client_id=my-client-id" \ # -d "client_secret=my-client-secret" \ # -d "scope=read write" ``` -------------------------------- ### Refresh Token Flow Request Source: https://context7.com/go-oauth2/oauth2/llms.txt Example using curl to obtain a new access token using a refresh token. This is used when an existing access token has expired. ```bash # Refresh an expired access token # curl -X POST http://localhost:9096/token \ # -d "grant_type=refresh_token" \ # -d "refresh_token=5FBLXQ47XJ2MGTY8YRZQ8W" \ # -d "client_id=my-client-id" \ # -d "client_secret=my-client-secret" ``` -------------------------------- ### Create and Configure In-Memory Client Store Source: https://context7.com/go-oauth2/oauth2/llms.txt Initialize an in-memory client store and register clients with their IDs, secrets, and domains. Public clients do not require a secret. ```go import ( "github.com/go-oauth2/oauth2/v4/models" "github.com/go-oauth2/oauth2/v4/store" ) // Create in-memory client store clientStore := store.NewClientStore() // Register clients clientStore.Set("web-app", &models.Client{ ID: "web-app", Secret: "web-app-secret", Domain: "https://myapp.example.com", Public: false, UserID: "owner-user-id", }) // Public client (mobile/SPA - no secret) clientStore.Set("mobile-app", &models.Client{ ID: "mobile-app", Secret: "", Domain: "myapp://callback", Public: true, }) manager.MapClientStorage(clientStore) ``` -------------------------------- ### Initialize Golang OAuth 2.0 Server Source: https://context7.com/go-oauth2/oauth2/llms.txt Sets up the OAuth 2.0 server with in-memory token storage, a test client, and configures handlers for authorization and token requests. Ensure to replace in-memory storage with a persistent solution for production. ```go package main import ( "context" "log" "net/http" "github.com/go-oauth2/oauth2/v4/errors" "github.com/go-oauth2/oauth2/v4/manage" "github.com/go-oauth2/oauth2/v4/models" "github.com/go-oauth2/oauth2/v4/server" "github.com/go-oauth2/oauth2/v4/store" ) func main() { // Create a manager with default token generators manager := manage.NewDefaultManager() // Configure token storage (in-memory for development) manager.MustTokenStorage(store.NewMemoryTokenStore()) // Configure client storage with a test client clientStore := store.NewClientStore() clientStore.Set("my-client-id", &models.Client{ ID: "my-client-id", Secret: "my-client-secret", Domain: "http://localhost:8080", }) manager.MapClientStorage(clientStore) // Create the OAuth 2.0 server srv := server.NewDefaultServer(manager) srv.SetAllowGetAccessRequest(true) srv.SetClientInfoHandler(server.ClientFormHandler) // Configure user authorization handler srv.UserAuthorizationHandler = func(w http.ResponseWriter, r *http.Request) (userID string, err error) { // In production, authenticate the user and return their ID return "user-123", nil } // Configure error handlers srv.SetInternalErrorHandler(func(err error) (re *errors.Response) { log.Println("Internal Error:", err.Error()) return }) srv.SetResponseErrorHandler(func(re *errors.Response) { log.Println("Response Error:", re.Error.Error()) }) // Mount OAuth endpoints http.HandleFunc("/authorize", func(w http.ResponseWriter, r *http.Request) { err := srv.HandleAuthorizeRequest(w, r) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) } }) http.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) { srv.HandleTokenRequest(w, r) }) log.Println("OAuth server running on :9096") log.Fatal(http.ListenAndServe(":9096", nil)) } ``` -------------------------------- ### Create OAuth 2.0 Server Source: https://github.com/go-oauth2/oauth2/blob/master/README.md Sets up a default OAuth 2.0 server with memory token and client stores, handling authorization and token requests. Requires specific handlers for user authorization and error responses. ```go package main import ( "log" "net/http" "github.com/go-oauth2/oauth2/v4/errors" "github.com/go-oauth2/oauth2/v4/manage" "github.com/go-oauth2/oauth2/v4/models" "github.com/go-oauth2/oauth2/v4/server" "github.com/go-oauth2/oauth2/v4/store" ) func main() { manager := manage.NewDefaultManager() // token memory store manager.MustTokenStorage(store.NewMemoryTokenStore()) // client memory store clientStore := store.NewClientStore() clientStore.Set("000000", &models.Client{ ID: "000000", Secret: "999999", Domain: "http://localhost", }) manager.MapClientStorage(clientStore) srv := server.NewDefaultServer(manager) srv.SetAllowGetAccessRequest(true) srv.SetClientInfoHandler(server.ClientFormHandler) srv.UserAuthorizationHandler = func(w http.ResponseWriter, r *http.Request) (userID string, err error) { return "000000", nil } srv.SetInternalErrorHandler(func(err error) (re *errors.Response) { log.Println("Internal Error:", err.Error()) return }) srv.SetResponseErrorHandler(func(re *errors.Response) { log.Println("Response Error:", re.Error.Error()) }) http.HandleFunc("/authorize", func(w http.ResponseWriter, r *http.Request) { err := srv.HandleAuthorizeRequest(w, r) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) } }) http.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) { srv.HandleTokenRequest(w, r) }) log.Fatal(http.ListenAndServe(":9096", nil)) } ``` -------------------------------- ### Configure File-Based Token Store Source: https://context7.com/go-oauth2/oauth2/llms.txt Initialize a file-based token store for persistent token storage. Specify the database file name. ```go import "github.com/go-oauth2/oauth2/v4/store" // File-based token store (persistent) fileStore, err := store.NewFileTokenStore("oauth_tokens.db") if err != nil { log.Fatal(err) } manager.MapTokenStorage(fileStore) ``` -------------------------------- ### Configure In-Memory Token Store Source: https://context7.com/go-oauth2/oauth2/llms.txt Set up an in-memory token store for development or testing purposes. Handles errors during initialization. ```go import "github.com/go-oauth2/oauth2/v4/store" // In-memory token store (development) memStore, err := store.NewMemoryTokenStore() if err != nil { log.Fatal(err) } manager.MustTokenStorage(memStore, nil) ``` -------------------------------- ### Complete OAuth 2.0 Server in Go Source: https://context7.com/go-oauth2/oauth2/llms.txt This Go program implements a full OAuth 2.0 server. It requires setting up a token manager, client store, and defining handlers for authorization, token requests, and protected resources. Use this as a foundation for building your own authorization server. ```go package main import ( "context" "encoding/json" "log" "net/http" "time" "github.com/go-oauth2/oauth2/v4/errors" "github.com/go-oauth2/oauth2/v4/manage" "github.com/go-oauth2/oauth2/v4/models" "github.com/go-oauth2/oauth2/v4/server" "github.com/go-oauth2/oauth2/v4/store" ) func main() { manager := manage.NewDefaultManager() manager.MustTokenStorage(store.NewMemoryTokenStore()) clientStore := store.NewClientStore() clientStore.Set("client-id", &models.Client{ ID: "client-id", Secret: "client-secret", Domain: "http://localhost:8080", }) manager.MapClientStorage(clientStore) srv := server.NewDefaultServer(manager) srv.SetAllowGetAccessRequest(true) srv.SetClientInfoHandler(server.ClientFormHandler) srv.UserAuthorizationHandler = func(w http.ResponseWriter, r *http.Request) (string, error) { // Implement your user authentication logic return "user-id", nil } srv.SetPasswordAuthorizationHandler(func(ctx context.Context, clientID, username, password string) (string, error) { if username == "demo" && password == "demo" { return username, nil } return "", errors.ErrAccessDenied }) // Authorization endpoint http.HandleFunc("/oauth/authorize", func(w http.ResponseWriter, r *http.Request) { if err := srv.HandleAuthorizeRequest(w, r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) } }) // Token endpoint http.HandleFunc("/oauth/token", func(w http.ResponseWriter, r *http.Request) { srv.HandleTokenRequest(w, r) }) // Protected resource endpoint http.HandleFunc("/api/me", func(w http.ResponseWriter, r *http.Request) { token, err := srv.ValidationBearerToken(r) if err != nil { w.WriteHeader(http.StatusUnauthorized) json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) return } json.NewEncoder(w).Encode(map[string]interface{}{ "client_id": token.GetClientID(), "user_id": token.GetUserID(), "scope": token.GetScope(), "expires_in": int64(token.GetAccessCreateAt().Add(token.GetAccessExpiresIn()).Sub(time.Now()).Seconds()), }) }) log.Println("OAuth 2.0 Server running on :9096") log.Println("Authorization endpoint: http://localhost:9096/oauth/authorize") log.Println("Token endpoint: http://localhost:9096/oauth/token") log.Fatal(http.ListenAndServe(":9096", nil)) } ``` -------------------------------- ### Configure Password Grant Server Source: https://context7.com/go-oauth2/oauth2/llms.txt Set up the server to handle user credentials directly for token exchange. Ensure user credentials are validated against your user store. ```go // Server configuration for password grant srv.SetPasswordAuthorizationHandler(func(ctx context.Context, clientID, username, password string) (userID string, err error) { // Validate user credentials against your user store if username == "test" && password == "test" { return "user-123", nil } return "", errors.ErrAccessDenied }) ``` -------------------------------- ### Enable PKCE Requirement on Server Source: https://context7.com/go-oauth2/oauth2/llms.txt Configure the OAuth2 server to enforce PKCE for authorization code grants. Allows plain and S256 challenge methods. ```go import ( "github.com/go-oauth2/oauth2/v4" "github.com/go-oauth2/oauth2/v4/server" ) // Server configuration - enable PKCE requirement config := server.NewConfig() config.ForcePKCE = true // Require PKCE for all authorization code grants config.AllowedCodeChallengeMethods = []oauth2.CodeChallengeMethod{ oauth2.CodeChallengePlain, oauth2.CodeChallengeS256, } srv := server.NewServer(config, manager) ``` -------------------------------- ### Retrieve Client Information Source: https://context7.com/go-oauth2/oauth2/llms.txt Fetch client details from the ClientStore using the client ID. Handles errors if the client is not found. ```go import ( "fmt" "log" ) // Retrieve client info clientInfo, err := clientStore.GetByID(ctx, "web-app") if err != nil { log.Fatal("Client not found") } fmt.Printf("Client domain: %s\n", clientInfo.GetDomain()) ``` -------------------------------- ### Configure JWT Access Token Generation (HMAC) Source: https://context7.com/go-oauth2/oauth2/llms.txt Set up JWT access token generation using HMAC signing. This involves specifying a key ID, a secret key, and the desired signing method. ```go import ( "github.com/go-oauth2/oauth2/v4/generates" "github.com/golang-jwt/jwt/v5" ) // Configure JWT access token generation with HMAC manager.MapAccessGenerate(generates.NewJWTAccessGenerate( "key-id-1", // Key ID (optional, for key rotation) []byte("my-secret-key-32byte"), // Secret key jwt.SigningMethodHS512, // Signing method )) ``` -------------------------------- ### Generate PKCE Code Challenge Source: https://context7.com/go-oauth2/oauth2/llms.txt Client-side implementation for PKCE: generate a code verifier, then compute the code challenge using SHA256. ```go import "crypto/sha256" // Client implementation: // 1. Generate code_verifier (43-128 character random string) codeVerifier := "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" // 2. Generate code_challenge using S256 method hash := sha256.Sum256([]byte(codeVerifier)) codeChallenge := base64.RawURLEncoding.EncodeToString(hash[:]) ``` -------------------------------- ### Configure Custom URI Validation Source: https://context7.com/go-oauth2/oauth2/llms.txt Implement a custom handler to validate redirect URIs against the base URI. Ensures that the hostnames match. ```go import ( "errors" "net/url" ) // Configure custom URI validation manager.SetValidateURIHandler(func(baseURI, redirectURI string) error { base, _ := url.Parse(baseURI) redirect, _ := url.Parse(redirectURI) if base.Host != redirect.Host { return errors.ErrInvalidRedirectURI } return nil }) ``` -------------------------------- ### Configure OAuth2 Manager Settings Source: https://context7.com/go-oauth2/oauth2/llms.txt Set token expiration times and token configuration for different grant types. Default authorization code expiration is 10 minutes. ```go import ( t"time" "github.com/go-oauth2/oauth2/v4/manage" ) manager := manage.NewDefaultManager() // Configure authorization code expiration (default: 10 minutes) manager.SetAuthorizeCodeExp(time.Minute * 5) // Configure token expiration for each grant type manager.SetAuthorizeCodeTokenCfg(&manage.Config{ AccessTokenExp: time.Hour * 2, RefreshTokenExp: time.Hour * 24 * 3, IsGenerateRefresh: true, }) manager.SetImplicitTokenCfg(&manage.Config{ AccessTokenExp: time.Hour * 1, // No refresh token for implicit grant }) manager.SetPasswordTokenCfg(&manage.Config{ AccessTokenExp: time.Hour * 2, RefreshTokenExp: time.Hour * 24 * 7, IsGenerateRefresh: true, }) manager.SetClientTokenCfg(&manage.Config{ AccessTokenExp: time.Hour * 2, // No refresh token for client credentials }) ``` -------------------------------- ### Client Credentials Grant - Access Token Response Source: https://github.com/go-oauth2/oauth2/blob/master/example/README.md Sample JSON response for obtaining an access token using the Client Credentials Grant, suitable for machine-to-machine authentication. ```json { "access_token": "OA6ITALNMDOGD58C0SN-MG", "token_type": "Bearer", "expiry": "2019-02-12T11:10:35.864838+08:00" } ``` -------------------------------- ### Configure Refresh Token Behavior Source: https://context7.com/go-oauth2/oauth2/llms.txt Customize the behavior of refresh tokens, including expiry times and whether to generate new refresh tokens or remove old ones. ```go # Configure refresh token behavior manager.SetRefreshTokenCfg(&manage.RefreshingConfig{ AccessTokenExp: time.Hour * 2, RefreshTokenExp: time.Hour * 24 * 7, IsGenerateRefresh: true, // Generate new refresh token IsResetRefreshTime: true, // Reset refresh token expiry IsRemoveAccess: true, // Remove old access token IsRemoveRefreshing: true, // Remove old refresh token }) ``` -------------------------------- ### Parse and Verify JWT Access Token Source: https://context7.com/go-oauth2/oauth2/llms.txt Implement a function to parse and verify JWT access tokens on the resource server. This function checks the signing method and token validity. ```go // Parse and verify JWT access token on resource server func validateJWT(accessToken string) (*generates.JWTAccessClaims, error) { token, err := jwt.ParseWithClaims(accessToken, &generates.JWTAccessClaims{}, func(t *jwt.Token) (interface{}, error) { // Verify signing method if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"]) } return []byte("my-secret-key-32byte"), nil }) if err != nil { return nil, err } claims, ok := token.Claims.(*generates.JWTAccessClaims) if !ok || !token.Valid { return nil, errors.New("invalid token") } return claims, nil } ``` -------------------------------- ### Authorization Code Grant - Try Access Token Response Source: https://github.com/go-oauth2/oauth2/blob/master/example/README.md Sample JSON response when trying to access a resource with an access token obtained via the Authorization Code Grant. ```json { "client_id": "222222", "expires_in": 7195, "user_id": "000000" } ``` -------------------------------- ### Password Credentials Grant - Access Token Response Source: https://github.com/go-oauth2/oauth2/blob/master/example/README.md Sample JSON response for obtaining an access token using the Password Credentials Grant, which typically involves username and password. ```json { "access_token": "87JT3N6WOWANXVDNZFHY7Q", "token_type": "Bearer", "refresh_token": "LDIS6PXAVY-BXHPEDESWNG", "expiry": "2019-02-12T10:58:43.734902+08:00" } ``` -------------------------------- ### Generate JWT Access Tokens Source: https://github.com/go-oauth2/oauth2/blob/master/README.md Configures the OAuth2 manager to use JWT for generating access tokens with a specified signing method and secret key. Also shows how to parse and verify a JWT access token. ```go import ( "github.com/go-oauth2/oauth2/v4/generates" "github.com/dgrijalva/jwt-go" ) // ... manager.MapAccessGenerate(generates.NewJWTAccessGenerate("", []byte("00000000"), jwt.SigningMethodHS512)) // Parse and verify jwt access token token, err := jwt.ParseWithClaims(access, &generates.JWTAccessClaims{}, func(t *jwt.Token) (interface{}, error) { if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("parse error") } return []byte("00000000"), nil }) if err != nil { // panic(err) } claims, ok := token.Claims.(*generates.JWTAccessClaims) if !ok || !token.Valid { // panic("invalid token") } ``` -------------------------------- ### Set Pre-Redirect Error Handler Source: https://context7.com/go-oauth2/oauth2/llms.txt Customize error handling specifically for scenarios that involve redirects. This handler can intercept errors and provide alternative responses, such as custom error pages. ```go // Pre-redirect error handler - custom handling before redirect srv.PreRedirectErrorHandler = func(w http.ResponseWriter, req *AuthorizeRequest, err error) error { // Custom error page instead of redirect if err == errors.ErrAccessDenied { http.Redirect(w, req.Request, "/access-denied", http.StatusFound) return nil // Prevent default redirect } return err // Use default redirect behavior } ``` -------------------------------- ### Authorization Code Grant - Access Token Response Source: https://github.com/go-oauth2/oauth2/blob/master/example/README.md Sample JSON response received after a successful Authorization Code Grant flow, containing the access token and related details. ```json { "access_token": "GIGXO8XWPQSAUGOYQGTV8Q", "token_type": "Bearer", "refresh_token": "5FBLXQ47XJ2MGTY8YRZQ8W", "expiry": "2019-01-08T01:53:45.868194+08:00" } ``` -------------------------------- ### Refresh Token Grant - Access Token Response Source: https://github.com/go-oauth2/oauth2/blob/master/example/README.md Sample JSON response after successfully refreshing an access token using a refresh token. This response includes a new access token and potentially a new refresh token. ```json { "access_token": "0IIL4_AJN2-SR0JEYZVQWG", "token_type": "Bearer", "refresh_token": "AG6-63MLXUEFUV2Q_BLYIW", "expiry": "2019-01-09T23:03:16.374062+08:00" } ``` -------------------------------- ### Customize Access Token Expiration Handler Source: https://context7.com/go-oauth2/oauth2/llms.txt Set custom lifetimes for access tokens. This handler allows for dynamic expiration durations based on request parameters like scope. ```go // Access token expiration handler - custom token lifetime srv.AccessTokenExpHandler = func(w http.ResponseWriter, r *http.Request) (time.Duration, error) { // Different expiration based on scope if strings.Contains(r.FormValue("scope"), "remember") { return time.Hour * 24 * 30, nil // 30 days } return time.Hour * 2, nil // Default 2 hours } ``` -------------------------------- ### Restrict Grant Types Per Client Source: https://context7.com/go-oauth2/oauth2/llms.txt Control which grant types are allowed for specific clients. This handler enforces client-specific authorization rules. ```go // Client authorization handler - restrict grant types per client srv.ClientAuthorizedHandler = func(clientID string, grant oauth2.GrantType) (bool, error) { // Only allow password grant for specific clients if grant == oauth2.PasswordCredentials && clientID != "trusted-client" { return false, nil } return true, nil } ``` -------------------------------- ### Validate Bearer Token for Protected Resources Source: https://context7.com/go-oauth2/oauth2/llms.txt Implement a handler for protected endpoints that validates the incoming bearer token using `ValidationBearerToken`. This ensures only authorized clients can access resources. ```go # Protected endpoint handler http.HandleFunc("/api/resource", func(w http.ResponseWriter, r *http.Request) { // Validate the bearer token tokenInfo, err := srv.ValidationBearerToken(r) if err != nil { http.Error(w, err.Error(), http.StatusUnauthorized) return } // Token is valid - access token info response := map[string]interface{}{ "client_id": tokenInfo.GetClientID(), "user_id": tokenInfo.GetUserID(), "scope": tokenInfo.GetScope(), "expires_in": int64(tokenInfo.GetAccessCreateAt().Add(tokenInfo.GetAccessExpiresIn()).Sub(time.Now()).Seconds()), } json.NewEncoder(w).Encode(response) }) ``` -------------------------------- ### Set Internal Error Handler Source: https://context7.com/go-oauth2/oauth2/llms.txt Customize how internal OAuth2 errors are handled. This allows for logging errors and optionally overriding the default error response format. ```go import "github.com/go-oauth2/oauth2/v4/errors" // Internal error handler - log errors, optionally override response srv.SetInternalErrorHandler(func(err error) *errors.Response { log.Printf("Internal OAuth error: %v", err) // Return nil to use default error response // Or return custom response: return &errors.Response{ Error: errors.ErrServerError, Description: "An internal error occurred", StatusCode: 500, } }) ``` -------------------------------- ### Add Extension Fields to Token Response Source: https://context7.com/go-oauth2/oauth2/llms.txt Include custom fields in the OAuth2 token response. This handler receives token information and returns a map of additional key-value pairs. ```go // Extension fields handler - add custom fields to token response srv.ExtensionFieldsHandler = func(ti oauth2.TokenInfo) map[string]interface{} { return map[string]interface{}{ "custom_field": "custom_value", "user_id": ti.GetUserID(), } } ``` -------------------------------- ### Validate Client Scope Source: https://context7.com/go-oauth2/oauth2/llms.txt Validate if a client is permitted to request a specific scope. This handler checks client ID against allowed scopes. ```go // Client scope handler - validate scope for client srv.ClientScopeHandler = func(tgr *oauth2.TokenGenerateRequest) (bool, error) { // Check if client is allowed to request this scope if tgr.Scope == "admin" && tgr.ClientID != "admin-client" { return false, nil } return true, nil } ``` -------------------------------- ### Customize Authorization Scope Handler Source: https://context7.com/go-oauth2/oauth2/llms.txt Modify or validate the requested scope during authorization. This handler can deny specific scopes or alter the requested scope before proceeding. ```go // Authorize scope handler - modify or validate requested scope srv.AuthorizeScopeHandler = func(w http.ResponseWriter, r *http.Request) (scope string, err error) { // Optionally modify or restrict scope requestedScope := r.FormValue("scope") if requestedScope == "admin" { return "", errors.ErrInvalidScope // Deny admin scope } return requestedScope, nil } ``` -------------------------------- ### Set Response Error Handler Source: https://context7.com/go-oauth2/oauth2/llms.txt Modify OAuth2 error responses before they are sent to the client. This handler can add custom headers or log detailed error information. ```go // Response error handler - modify error before sending srv.SetResponseErrorHandler(func(re *errors.Response) { log.Printf("OAuth error response: %s - %s", re.Error, re.Description) // Optionally modify the response re.SetHeader("X-Error-ID", generateErrorID()) }) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.