README
¶
Golang OAuth 2.0 Server
An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications.
Protocol Flow
+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- Authorization Grant -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+
Quick Start
Download and install
go get -u -v git.gurkengewuerz.de/crypbite/oauth2/...
Create file server.go
package main
import (
"log"
"net/http"
"git.gurkengewuerz.de/crypbite/oauth2/errors"
"git.gurkengewuerz.de/crypbite/oauth2/manage"
"git.gurkengewuerz.de/crypbite/oauth2/models"
"git.gurkengewuerz.de/crypbite/oauth2/server"
"git.gurkengewuerz.de/crypbite/oauth2/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.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))
}
Build and run
go build server.go
./server
Open in your web browser
{
"access_token": "J86XVRYSNFCFI233KXDL0Q",
"expires_in": 7200,
"scope": "read",
"token_type": "Bearer"
}
Features
- Easy to use
- Based on the RFC 6749 implementation
- Token storage support TTL
- Support custom expiration time of the access token
- Support custom extension field
- Support custom scope
- Support jwt to generate access tokens
Example
A complete example of simulation authorization code model
Simulation examples of authorization code model, please check example
Use jwt to generate access tokens
import (
"git.gurkengewuerz.de/crypbite/oauth2/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")
}
Store Implements
- BuntDB(default store)
- Redis
- MongoDB
- MySQL
- MySQL (Provides both client and token store)
- PostgreSQL
- DynamoDB
- XORM
- GORM
- Firestore
Handy Utilities
MIT License
Copyright (c) 2016 Lyric
Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AccessGenerate ¶
type AccessGenerate interface {
Token(ctx context.Context, data *GenerateBasic, isGenRefresh bool) (access, refresh string, err error)
}
AccessGenerate generate the access and refresh tokens interface
type AuthorizeGenerate ¶
type AuthorizeGenerate interface {
Token(ctx context.Context, data *GenerateBasic) (code string, err error)
}
AuthorizeGenerate generate the authorization code interface
type ClientInfo ¶
type ClientInfo interface { GetID() string GetSecret() string GetDomain() string GetUserID() string }
ClientInfo the client information model interface
type ClientPasswordVerifier ¶
ClientPasswordVerifier the password handler interface
type ClientStore ¶
type ClientStore interface { // according to the ID for the client information GetByID(ctx context.Context, id string) (ClientInfo, error) }
ClientStore the client information storage interface
type GenerateBasic ¶
type GenerateBasic struct { Client ClientInfo UserID string CreateAt time.Time TokenInfo TokenInfo Request *http.Request }
GenerateBasic provide the basis of the generated token data
type GrantType ¶
type GrantType string
GrantType authorization model
type Manager ¶
type Manager interface { // get the client information GetClient(ctx context.Context, clientID string) (cli ClientInfo, err error) // generate the authorization token(code) GenerateAuthToken(ctx context.Context, rt ResponseType, tgr *TokenGenerateRequest) (authToken TokenInfo, err error) // generate the access token GenerateAccessToken(ctx context.Context, rt GrantType, tgr *TokenGenerateRequest) (accessToken TokenInfo, err error) // refreshing an access token RefreshAccessToken(ctx context.Context, tgr *TokenGenerateRequest) (accessToken TokenInfo, err error) // use the access token to delete the token information RemoveAccessToken(ctx context.Context, access string) (err error) // use the refresh token to delete the token information RemoveRefreshToken(ctx context.Context, refresh string) (err error) // according to the access token for corresponding token information LoadAccessToken(ctx context.Context, access string) (ti TokenInfo, err error) // according to the refresh token for corresponding token information LoadRefreshToken(ctx context.Context, refresh string) (ti TokenInfo, err error) }
Manager authorization management interface
type ResponseType ¶
type ResponseType string
ResponseType the type of authorization request
const ( Code ResponseType = "code" Token ResponseType = "token" )
define the type of authorization request
func (ResponseType) String ¶
func (rt ResponseType) String() string
type TokenGenerateRequest ¶
type TokenGenerateRequest struct { ClientID string ClientSecret string UserID string RedirectURI string Scope string Code string Refresh string AccessTokenExp time.Duration Request *http.Request }
TokenGenerateRequest provide to generate the token request parameters
type TokenInfo ¶
type TokenInfo interface { New() TokenInfo GetClientID() string SetClientID(string) GetUserID() string SetUserID(string) GetRedirectURI() string SetRedirectURI(string) GetScope() string SetScope(string) GetCode() string SetCode(string) GetCodeCreateAt() time.Time SetCodeCreateAt(time.Time) GetCodeExpiresIn() time.Duration SetCodeExpiresIn(time.Duration) GetAccess() string SetAccess(string) GetAccessCreateAt() time.Time SetAccessCreateAt(time.Time) GetAccessExpiresIn() time.Duration SetAccessExpiresIn(time.Duration) GetRefresh() string SetRefresh(string) GetRefreshCreateAt() time.Time SetRefreshCreateAt(time.Time) GetRefreshExpiresIn() time.Duration SetRefreshExpiresIn(time.Duration) }
TokenInfo the token information model interface
type TokenStore ¶
type TokenStore interface { // create and store the new token information Create(ctx context.Context, info TokenInfo) error // delete the authorization code RemoveByCode(ctx context.Context, code string) error // use the access token to delete the token information RemoveByAccess(ctx context.Context, access string) error // use the refresh token to delete the token information RemoveByRefresh(ctx context.Context, refresh string) error // use the authorization code for token information data GetByCode(ctx context.Context, code string) (TokenInfo, error) // use the access token for token information data GetByAccess(ctx context.Context, access string) (TokenInfo, error) // use the refresh token for token information data GetByRefresh(ctx context.Context, refresh string) (TokenInfo, error) }
TokenStore the token information storage interface