Raiqub/oauth is a library for the Go Programming Language. It provides an implementation of OAuth 2.0 features.
To install raiqub/oauth library run the following command:
go get gopkg.in/raiqub/oauth.v2
To import this package, add the following line to your code:
import "gopkg.in/raiqub/oauth.v2"
To create a server to handle token endpoint, as defined by OAuth 2.0 specification, an adapter must be created to define the following operations: find a client, create new access token, validate refresh token and validate user credentials.
To a type be qualified as an adapter must implements the TokenAdapter methods. As shown by the example below:
import (
"gopkg.in/raiqub/oauth.v2"
"gopkg.in/raiqub/slice.v1"
)
type MyAdapter struct {
// Should has fields that allow database connection
}
// NewMyAdapter creates a new instance of MyAdapter.
func NewMyAdapter() *MyAdapter {
return &MyAdapter{}
}
// FindClient gets the client information if valid.
func (a *MyAdapter) FindClient(c *oauth.TokenContext) *oauth.ClientEntry {
// Should retrieve from database
clientID, clientSecret := "example_client", "example_secret"
clientScopes := []string{"profile.write", "calendar.read"}
if c.HTTPUser != clientID ||
c.HTTPSecret != clientSecret {
return nil
}
return &oauth.ClientEntry{
ClientID: clientID,
ClientSecret: clientSecret,
ClientType: "public",
RedirectUris: []string{"http://client.example.com/callback"},
JavascriptOrigins: []string{"http://client.example.com"},
AllowedGrants: []string{oauth.GrantTypeClient},
AllowedScopes: clientScopes,
}
}
// NewAccessToken creates and returns a new access token.
func (a *MyAdapter) NewAccessToken(c *oauth.TokenContext) *oauth.TokenResponse {
// Should create an unique token (and state when applicable)
resp := oauth.NewTokenResponse(
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
"bearer",
3600,
"",
"profile.write calendar.read",
"CudYQpuw",
)
return &resp
}
// ValidateRefresh validate provided refresh token.
func (a *MyAdapter) ValidateRefresh(*oauth.TokenContext) bool {
// Should validate provided refresh token
// Use: c.RefreshToken
return false
}
// ValidateUser validate resource owner credentials for password grant type.
func (a *MyAdapter) ValidateUser(c *oauth.TokenContext) bool {
// Should validate provided user credentials
// Use: c.Username and c.Password
return false
}
Then you can use a TokenServer to handle token endpoint:
import (
"net/http"
"gopkg.in/raiqub/oauth.v2"
httptransport "gopkg.in/raiqub/oauth.v2/transport/http"
)
svcToken := oauth.NewTokenService(NewMyAdapter(),
// Accepts client_credentials and refresh_token
oauth.GrantTypeClient, oauth.GrantTypeRefresh)
srvToken := httptransport.NewTokenServer(svcToken)
http.HandleFunc("/token", srvToken.AccessTokenRequest)
http.ListenAndServe(":8080", nil)
Optionally new grant types can be accepted. To do that you will need to create a function that matchs TokenHandlerFunc function and SetHandler on server.
import "gopkg.in/raiqub/oauth.v2"
func MyHandler(adapter oauth.TokenAdapter, c *oauth.TokenContext,
) (*oauth.TokenResponse, *oauth.Error) {
// Validates client authentication and authorization
var oerr *oauth.Error
c.Client, oerr = oauth.AuthClient(adapter, c)
if oerr != nil {
return nil, oerr
}
// You should implement here your logic
}
import (
"net/http"
"gopkg.in/raiqub/oauth.v2"
httptransport "gopkg.in/raiqub/oauth.v2/transport/http"
)
svcToken := oauth.NewTokenService(NewMyAdapter(),
// Accepts client_credentials and refresh_token
oauth.GrantTypeClient, oauth.GrantTypeRefresh)
// Adds a custom handler
srvToken.SetHandler("urn:custom:myhandler", MyHandler)
srvToken := httptransport.NewTokenServer(svcToken)
http.HandleFunc("/token", srvToken.AccessTokenRequest)
http.ListenAndServe(":8080", nil)
For reference and examples browse library documentation.
raiqub/oauth is made available under the Apache Version 2.0 License.