go-oauth2/oauth2

repository·master·Indexed 25 days ago

https://github.com/go-oauth2/oauth2

A Golang implementation of the OAuth 2.0 protocol (RFC 6749) for secure authorization in web, mobile, and desktop applications. The library supports multiple grant types including Authorization Code, Password Credentials, Client Credentials, and Refresh Token flows, as well as PKCE. It provides a flexible Server and Manager interface with support for various storage backends such as Redis, MongoDB, MySQL, PostgreSQL, DynamoDB, and GORM, and allows for JWT-based access token generation.

Tokens
3.9K
Snippets
5
Records
32
Agent score
86%

What's inside go-oauth2/oauth2

  1. Run the OAuth2 Server and Client examples

    master

    To test the library's functionality, you can run the provided example server and client.

    1. Start the Server: Navigate to the server directory, build, and run the server.go file.
    2. Start the Client: Navigate to the client directory, build, and run the client.go file.
    # Run Server
    $ cd example/server
    $ go build server.go
    $ ./server
    
    # Run Client
    $ cd example/client
    $ go build client.go
    $ ./client
  2. Quick Start: Implement a basic OAuth2 server

    master

    This example demonstrates how to set up a basic OAuth2 server using in-memory storage for both tokens and clients. It configures an authorization endpoint and a token endpoint.

    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))
    }
  3. Test Authorization Code Grant

    master

    The Authorization Code Grant flow can be tested by accessing the following endpoints in your browser:

    1. Obtain Tokens: Visit http://localhost:9094 to complete the authorization flow and receive an access_token, token_type, refresh_token, and expiry.
    2. Validate Access Token: Visit http://localhost:9094/try to see the token details, including client_id, expires_in, and user_id.
  4. Generate access tokens using JWT

    master

    You can configure the manager to use JWTs for access token generation. This requires the github.com/go-oauth2/oauth2/v4/generates package and a JWT library like github.com/dgrijalva/jwt-go.

    import (
    	"github.com/go-oauth2/oauth2/v4/generates"
    	"github.com/dgrijalva/jwt-go"
    )
    
    // ...
    // Configure manager to use JWT generation
    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 {
    	// handle error
    }
    
    claims, ok := token.Claims.(*generates.JWTAccessClaims)
    if !ok || !token.Valid {
    	// handle invalid token
    }
  5. Supported Storage Implementations

    master

    The library supports various storage backends for clients and tokens. Available implementations include:

    • BuntDB (default)
    • Redis
    • MongoDB
    • MySQL
    • PostgreSQL
    • DynamoDB
    • XORM
    • GORM
    • Firestore
    • Hazelcast (token only)
  6. Use ClientStore for in-memory client credential storage

    master
    The ClientStore provides an in-memory implementation of client credential storage using a thread-safe map. It allows you to store and retrieve oauth2.ClientInfo objects by their ID. This is useful for simple setups or testing where persistent storage like a database is not required.
  7. Handle Authorization Requests

    master

    To handle an OAuth2 authorization request (e.g., via a browser redirect), use the HandleAuthorizeRequest method. This method performs the following steps:

    1. Validates the incoming request (ValidationAuthorizeRequest).
    2. Invokes the UserAuthorizationHandler to identify the user.
    3. Optionally invokes AuthorizeScopeHandler to refine requested scopes.
    4. Generates the authorization token (or code) via GetAuthorizeToken.
    5. Redirects the user back to the redirect_uri with the resulting data (e.g., the code).