Documentation ¶
Overview ¶
Package introspection provide auth strategy to authenticate, incoming HTTP requests using the oauth2 token introspection endpoint, as defined in RFC 7662. This authentication strategy makes it easy to introduce apps, into a oauth2 authorization framework to be used by resource servers or other internal servers.
Example ¶
package main import ( "fmt" "net/http" "net/http/httptest" "github.com/shaj13/libcache" "github.com/shaj13/go-guardian/v2/auth/strategies/oauth2/introspection" _ "github.com/shaj13/libcache/lru" ) func main() { srv := AuthrizationServer() opt := introspection.SetHTTPClient(srv.Client()) strategy := introspection.New(srv.URL, libcache.LRU.New(0), opt) r, _ := http.NewRequest("GET", "/protected/resource", nil) r.Header.Set("Authorization", "Bearer <oauth2-token>") info, err := strategy.Authenticate(r.Context(), r) fmt.Println(info.GetUserName(), err) } func AuthrizationServer() *httptest.Server { h := func(w http.ResponseWriter, r *http.Request) { const body = ` { "active": true, "client_id": "l238j323ds-23ij4", "username": "jdoe", "scope": "read write dolphin", "sub": "Z5O3upPC88QrAjx00dis", "aud": "https://protected.example.net/resource", "iss": "https://server.example.com/", "iat": 1419350238, "extension_field": "twenty-seven" } ` w.WriteHeader(200) w.Write([]byte(body)) } return httptest.NewServer(http.HandlerFunc(h)) }
Output: jdoe <nil>
Example (Scope) ¶
package main import ( "fmt" "net/http" "net/http/httptest" "github.com/shaj13/libcache" "github.com/shaj13/go-guardian/v2/auth/strategies/oauth2/introspection" "github.com/shaj13/go-guardian/v2/auth/strategies/token" _ "github.com/shaj13/libcache/lru" ) func main() { opt := token.SetScopes(token.NewScope("dolphin", "/dolphin", "GET|POST|PUT")) srv := AuthrizationServer() strategy := introspection.New(srv.URL, libcache.LRU.New(0), opt) r, _ := http.NewRequest("DELETE", "/dolphin", nil) r.Header.Set("Authorization", "Bearer <oauth2-token>") _, err := strategy.Authenticate(r.Context(), r) fmt.Println(err) } func AuthrizationServer() *httptest.Server { h := func(w http.ResponseWriter, r *http.Request) { const body = ` { "active": true, "client_id": "l238j323ds-23ij4", "username": "jdoe", "scope": "read write dolphin", "sub": "Z5O3upPC88QrAjx00dis", "aud": "https://protected.example.net/resource", "iss": "https://server.example.com/", "iat": 1419350238, "extension_field": "twenty-seven" } ` w.WriteHeader(200) w.Write([]byte(body)) } return httptest.NewServer(http.HandlerFunc(h)) }
Output: strategies/token: The access token scopes do not grant access to the requested resource
Index ¶
- func GetAuthenticateFunc(addr string, opts ...auth.Option) token.AuthenticateFunc
- func New(addr string, c auth.Cache, opts ...auth.Option) auth.Strategy
- func SetAuthorizationToken(token string) auth.Option
- func SetBasicAuth(clientid, clinetsecret string) auth.Option
- func SetClaimResolver(c oauth2.ClaimsResolver) auth.Option
- func SetClientTransport(rt http.RoundTripper) auth.Option
- func SetErrorResolver(e oauth2.ErrorResolver) auth.Option
- func SetHTTPClient(c *http.Client) auth.Option
- func SetTLSConfig(tls *tls.Config) auth.Option
- func SetVerifyOptions(opts claims.VerifyOptions) auth.Option
- type Claims
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetAuthenticateFunc ¶
func GetAuthenticateFunc(addr string, opts ...auth.Option) token.AuthenticateFunc
GetAuthenticateFunc return function to authenticate request using oauth2 token introspection endpoint. The returned function typically used with the token strategy.
func New ¶
New return strategy authenticate request using oauth2 token introspection endpoint.
New is similar to:
fn := introspection.GetAuthenticateFunc(addr, opts...) token.New(fn, cache, opts...)
func SetAuthorizationToken ¶
SetAuthorizationToken sets the introspection request's Authorization header to use HTTP Bearer Authentication with the provided token.
func SetBasicAuth ¶
SetBasicAuth sets the introspection request's Authorization header to use HTTP Basic Authentication with the provided clientid and clientsecret.
func SetClaimResolver ¶
func SetClaimResolver(c oauth2.ClaimsResolver) auth.Option
SetClaimResolver sets the introspection strategy ClaimResolver to resolve the authorization claim response. Default: introspection.Claim
Example ¶
package main import ( "errors" "fmt" "net/http" "net/http/httptest" "github.com/shaj13/libcache" "github.com/shaj13/go-guardian/v2/auth" "github.com/shaj13/go-guardian/v2/auth/claims" "github.com/shaj13/go-guardian/v2/auth/strategies/oauth2" "github.com/shaj13/go-guardian/v2/auth/strategies/oauth2/introspection" _ "github.com/shaj13/libcache/lru" ) type ExampleClaims struct { ExtensionField string `json:"extension_field"` *introspection.Claims } func (c ExampleClaims) New() oauth2.ClaimsResolver { claim := introspection.Claims{}.New().(*introspection.Claims) return &ExampleClaims{Claims: claim} } func (c ExampleClaims) Resolve() auth.Info { return c } func (c ExampleClaims) Verify(opts claims.VerifyOptions) error { if v, ok := opts.Extra["extension_field"]; ok { str, ok := v.(string) if !ok { panic("Expected VerifyOptions.extension_field of type string") } if str != c.ExtensionField { return errors.New("ExampleClaim: Invalid ExtensionField") } } return c.Standard.Verify(opts) } func main() { srv := AuthrizationServer() opt := introspection.SetClaimResolver(new(ExampleClaims)) strategy := introspection.New(srv.URL, libcache.LRU.New(0), opt) r, _ := http.NewRequest("GEt", "/protected/resource", nil) r.Header.Set("Authorization", "Bearer <oauth2-token>") info, err := strategy.Authenticate(r.Context(), r) fmt.Println(info.(ExampleClaims).ExtensionField, err) } func AuthrizationServer() *httptest.Server { h := func(w http.ResponseWriter, r *http.Request) { const body = ` { "active": true, "client_id": "l238j323ds-23ij4", "username": "jdoe", "scope": "read write dolphin", "sub": "Z5O3upPC88QrAjx00dis", "aud": "https://protected.example.net/resource", "iss": "https://server.example.com/", "iat": 1419350238, "extension_field": "twenty-seven" } ` w.WriteHeader(200) w.Write([]byte(body)) } return httptest.NewServer(http.HandlerFunc(h)) }
Output: twenty-seven <nil>
func SetClientTransport ¶
func SetClientTransport(rt http.RoundTripper) auth.Option
SetClientTransport sets underlying http client transport.
func SetErrorResolver ¶
func SetErrorResolver(e oauth2.ErrorResolver) auth.Option
SetErrorResolver sets the introspection strategy ErrorResolver to resolve the authorization error response. Default: oauth2.ResponseError
func SetHTTPClient ¶
SetHTTPClient sets underlying http client.
func SetTLSConfig ¶
SetTLSConfig ssets underlying http client tls.
func SetVerifyOptions ¶
func SetVerifyOptions(opts claims.VerifyOptions) auth.Option
SetVerifyOptions sets the introspection strategy to verify authorization response.
Example ¶
package main import ( "fmt" "net/http" "net/http/httptest" "github.com/shaj13/libcache" "github.com/shaj13/go-guardian/v2/auth/claims" "github.com/shaj13/go-guardian/v2/auth/strategies/oauth2/introspection" _ "github.com/shaj13/libcache/lru" ) func main() { srv := AuthrizationServer() client := introspection.SetHTTPClient(srv.Client()) vopts := introspection.SetVerifyOptions( claims.VerifyOptions{ Issuer: "https://server.example.org", }) strategy := introspection.New(srv.URL, libcache.LRU.New(0), client, vopts) r, _ := http.NewRequest("GEt", "/protected/resource", nil) r.Header.Set("Authorization", "Bearer <oauth2-token>") info, err := strategy.Authenticate(r.Context(), r) fmt.Println(info, err) } func AuthrizationServer() *httptest.Server { h := func(w http.ResponseWriter, r *http.Request) { const body = ` { "active": true, "client_id": "l238j323ds-23ij4", "username": "jdoe", "scope": "read write dolphin", "sub": "Z5O3upPC88QrAjx00dis", "aud": "https://protected.example.net/resource", "iss": "https://server.example.com/", "iat": 1419350238, "extension_field": "twenty-seven" } ` w.WriteHeader(200) w.Write([]byte(body)) } return httptest.NewServer(http.HandlerFunc(h)) }
Output: <nil> strategies/oauth2/introspection: claims: standard claims issuer name does not match the expected issuer
Types ¶
type Claims ¶
type Claims struct { Active bool `json:"active"` ClientID string `json:"client_id"` UserName string `json:"username"` TokenType string `json:"token_type"` auth.Info *claims.Standard }
Claims represents introspection response as defined in RFC 7662. Claims implements auth.Info and oauth2.ClaimsResolver.
func (Claims) GetExpiresAt ¶
GetExpiresAt return's c.ExpiresAt.
func (Claims) GetUserName ¶
GetUserName return's c.Info.GetUserName if exist, Otherwise, it return c.UserName or c.Subject.
func (Claims) New ¶
func (c Claims) New() oauth2.ClaimsResolver
New return's a new Claims as oauth2.ClaimsResolver.