diff --git a/.gitignore b/.gitignore index daf913b..bbefbb9 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ _testmain.go *.exe *.test *.prof +/examples/server diff --git a/LICENSE b/LICENSE index dac9a1d..a3f5cc0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016 OAuth 2.0 +Copyright (c) 2016 Lyric Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 41d3e0f..388e18a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,95 @@ -# gin-server -Using Gin framework implementation OAuth 2.0 services +# Gin OAuth 2.0 Server + +> Using Gin framework implementation OAuth 2.0 services + +[![License][License-Image]][License-Url] [![ReportCard][ReportCard-Image]][ReportCard-Url] [![GoDoc][GoDoc-Image]][GoDoc-Url] + +## Quick Start + +### Download and install + +``` bash +$ go get -u github.com/go-oauth2/gin-server +``` + +### Create file `server.go` + +``` go +package main + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/go-oauth2/gin-server" + "gopkg.in/oauth2.v3/manage" + "gopkg.in/oauth2.v3/store" +) + +func main() { + manager := manage.NewDefaultManager() + manager.MustTokenStorage(store.NewMemoryTokenStore()) + manager.MapClientStorage(store.NewTestClientStore()) + + // Initialize the oauth2 service + server.InitServer(manager) + server.SetAllowGetAccessRequest(true) + + g := gin.Default() + g.GET("/token", server.HandleTokenRequest) + api := g.Group("/api") + { + api.Use(server.TokenAuth(func(c *gin.Context) string { + return c.Query("access_token") + })) + api.GET("/test", func(c *gin.Context) { + c.String(http.StatusOK, "ok") + }) + } + + g.Run(":9096") +} +``` + +### Build and run + +``` bash +$ go build server.go +$ ./server +``` + +### Open in your web browser + +#### The token information + +``` +http://localhost:9096/token?grant_type=client_credentials&client_id=1&client_secret=11&scope=read +``` + +``` json +{ + "access_token": "ZF1M7NKDNWUUX2TCDIMZZG", + "expires_in": 7200, + "scope": "read", + "token_type": "Bearer" +} +``` + +#### The authentication token + +``` +http://localhost:9096/api/test?access_token=ZF1M7NKDNWUUX2TCDIMZZG +``` + +## MIT License + +``` +Copyright (c) 2016 Lyric +``` + +[License-Url]: http://opensource.org/licenses/MIT +[License-Image]: https://img.shields.io/npm/l/express.svg +[ReportCard-Url]: https://goreportcard.com/report/github.com/go-oauth2/gin-server +[ReportCard-Image]: https://goreportcard.com/badge/github.com/go-oauth2/gin-server +[GoDoc-Url]: https://godoc.org/github.com/go-oauth2/gin-server +[GoDoc-Image]: https://godoc.org/github.com/go-oauth2/gin-server?status.svg \ No newline at end of file diff --git a/config.go b/config.go new file mode 100644 index 0000000..e20d177 --- /dev/null +++ b/config.go @@ -0,0 +1,81 @@ +package server + +import ( + "gopkg.in/oauth2.v3" + "gopkg.in/oauth2.v3/server" +) + +// SetTokenType token type +func SetTokenType(tokenType string) { + gServer.Config.TokenType = tokenType +} + +// SetAllowGetAccessRequest to allow GET requests for the token +func SetAllowGetAccessRequest(allow bool) { + gServer.Config.AllowGetAccessRequest = allow +} + +// SetAllowedResponseType allow the authorization types +func SetAllowedResponseType(types ...oauth2.ResponseType) { + gServer.Config.AllowedResponseTypes = types +} + +// SetAllowedGrantType allow the grant types +func SetAllowedGrantType(types ...oauth2.GrantType) { + gServer.Config.AllowedGrantTypes = types +} + +// SetClientInfoHandler get client info from request +func SetClientInfoHandler(handler server.ClientInfoHandler) { + gServer.ClientInfoHandler = handler +} + +// SetClientAuthorizedHandler check the client allows to use this authorization grant type +func SetClientAuthorizedHandler(handler server.ClientAuthorizedHandler) { + gServer.ClientAuthorizedHandler = handler +} + +// SetClientScopeHandler check the client allows to use scope +func SetClientScopeHandler(handler server.ClientScopeHandler) { + gServer.ClientScopeHandler = handler +} + +// SetUserAuthorizationHandler get user id from request authorization +func SetUserAuthorizationHandler(handler server.UserAuthorizationHandler) { + gServer.UserAuthorizationHandler = handler +} + +// SetPasswordAuthorizationHandler get user id from username and password +func SetPasswordAuthorizationHandler(handler server.PasswordAuthorizationHandler) { + gServer.PasswordAuthorizationHandler = handler +} + +// SetRefreshingScopeHandler check the scope of the refreshing token +func SetRefreshingScopeHandler(handler server.RefreshingScopeHandler) { + gServer.RefreshingScopeHandler = handler +} + +// SetResponseErrorHandler response error handling +func SetResponseErrorHandler(handler server.ResponseErrorHandler) { + gServer.ResponseErrorHandler = handler +} + +// SetInternalErrorHandler internal error handling +func SetInternalErrorHandler(handler server.InternalErrorHandler) { + gServer.InternalErrorHandler = handler +} + +// SetExtensionFieldsHandler in response to the access token with the extension of the field +func SetExtensionFieldsHandler(handler server.ExtensionFieldsHandler) { + gServer.ExtensionFieldsHandler = handler +} + +// SetAccessTokenExpHandler set expiration date for the access token +func SetAccessTokenExpHandler(handler server.AccessTokenExpHandler) { + gServer.AccessTokenExpHandler = handler +} + +// SetAuthorizeScopeHandler set scope for the access token +func SetAuthorizeScopeHandler(handler server.AuthorizeScopeHandler) { + gServer.AuthorizeScopeHandler = handler +} diff --git a/examples/server.go b/examples/server.go new file mode 100644 index 0000000..8bd65b7 --- /dev/null +++ b/examples/server.go @@ -0,0 +1,51 @@ +package main + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/go-oauth2/gin-server" + "gopkg.in/oauth2.v3/manage" + "gopkg.in/oauth2.v3/models" + "gopkg.in/oauth2.v3/store" +) + +func main() { + initOAuth2() + + g := gin.Default() + + g.GET("/authorize", server.HandleAuthorizeRequest) + g.POST("/token", server.HandleTokenRequest) + api := g.Group("/api") + { + api.Use(server.TokenAuth(tokenAuthHandle)) + api.GET("/test", testHandle) + } + + g.Run(":9096") +} + +func initOAuth2() { + manager := manage.NewDefaultManager() + // token store + manager.MustTokenStorage(store.NewMemoryTokenStore()) + // client store + manager.MapClientStorage(store.NewTestClientStore(&models.Client{ + ID: "999999", + Secret: "999999", + })) + + // Initialize the oauth2 service + server.InitServer(manager) + server.SetAllowGetAccessRequest(true) +} + +func tokenAuthHandle(c *gin.Context) (token string) { + token = c.Query("access_token") + return +} + +func testHandle(c *gin.Context) { + c.String(http.StatusOK, "ok") +} diff --git a/server.go b/server.go new file mode 100644 index 0000000..7a7f800 --- /dev/null +++ b/server.go @@ -0,0 +1,55 @@ +package server + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "gopkg.in/oauth2.v3" + "gopkg.in/oauth2.v3/server" +) + +var ( + gServer *server.Server +) + +// InitServer Initialize the service +func InitServer(manager oauth2.Manager) { + if err := manager.CheckInterface(); err != nil { + panic(err) + } + gServer = server.NewDefaultServer(manager) +} + +// HandleAuthorizeRequest the authorization request handling +func HandleAuthorizeRequest(c *gin.Context) { + err := gServer.HandleAuthorizeRequest(c.Writer, c.Request) + if err != nil { + c.AbortWithError(http.StatusBadRequest, err) + return + } + c.Abort() +} + +// HandleTokenRequest token request handling +func HandleTokenRequest(c *gin.Context) { + err := gServer.HandleTokenRequest(c.Writer, c.Request) + if err != nil { + c.AbortWithError(http.StatusBadRequest, err) + return + } + c.Abort() +} + +// TokenAuth Verify the access token of the middleware +func TokenAuth(tokenHandle func(c *gin.Context) string) gin.HandlerFunc { + return func(c *gin.Context) { + token := tokenHandle(c) + ti, err := gServer.Manager.LoadAccessToken(token) + if err != nil { + c.AbortWithError(http.StatusUnauthorized, err) + return + } + c.Set("Token", ti) + c.Next() + } +}