oauthMiddleware

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 5, 2022 License: Apache-2.0 Imports: 11 Imported by: 2

README

oauthMiddleware

Overview

Use this code to embed an authorisation handler in your HTTP server. The library provides a middleware http handler to validate bearer access tokens

(Microsoft's view on client credential flow)https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow

Note we are using active directory in our example but the code works with any openid compliant identity manager

How to use the client credentials flow in your HTTP Server

// logger must implement logger.LoggerInterface
type LoggerInterface interface {
Debugf(context.Context, string, ...interface{})
Infof(context.Context, string, ...interface{})
Errorf(context.Context, string, ...interface{})
}

// create a new instance
oauthMiddleware, err := oauthMiddleware.NewServer(ctx, logger.LoggerInterface, "myAppName", *openId.AuthCfg)

// Add a handler to your httpserver
if route.Auth {
    handler = oauthMiddleware.Handler(handler)
}

Sample configuration

See auth/openId package readme

Problems with token validation

If you ever have trouble validating a microsoft Azure AD token, this thread is useful

Paraphrasing:

  • For the failed case... if look at the Jwt.Header you will see a 'nonce'. This means you need special processing. Normal processing will fail. The 'nonce' is a mechanism, that allows the receiver to determine the token was forwarded. The signature is over the transformed nonce, so if you try and validate it directly, the signature will fail. Graph can determine that this token was replayed.

  • If you use scopes like "User.read", "openid", "profile", "email", ... you'll see that the audience value in the JWT access token will be set to graph.microsoft.com. So the token is indeed for graph, and not for your application.

  • Use the scope for the application on the Azure portal (API permissions -> Add -> My APIs -> Click on application and you will see the application APIs. Click on the API, Add. Then you will get the whole list of yours application APIs shown. Click on that you have just added and you will get the string like api://00000000-0000-0000-0000-0000f9e753c3/apiTestAdmin

  • On the Azure Portal, if you go to your application page, on the left there is a "Scopes" menu entry. This value need to be used as your scope. If you use the scope you have declared in your application on the portal, you'll see that the audience is the same value as the scope and the token will be valid! Our scope looks something like this : [https://.onmicrosoft.com//user_impersonation]

Set

"OpenidWellKnownConfigUrl":"https://login.microsoftonline.com/TENANTID/v2.0/.well-known/openid-configuration", "ClientId":"a4b85828-dc1f-xxxx-xxxx-xxxxxxxxxx", "Scope":"api://blah/blah/blah/user_impersonation", "Audience":"a4b85828-dc1f-xxxx-xxxx-xxxxxxxxxx",

and now the token validates

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FromAuthHeader

func FromAuthHeader(r *http.Request) (string, error)

FromAuthHeader is a "TokenExtractor" that takes a give request and extracts the JWT token from the Authorization header.

func GetClaims

func GetClaims(r *http.Request, logger logger.LoggerInterface) (claims map[string]interface{}, err error)

used outside of the auth flow to retrieve claims from the token

func OnError

func OnError(w http.ResponseWriter, r *http.Request, err string)

Types

type AuthMiddleware

type AuthMiddleware struct {
	Options AuthMiddlewareOptions
	// contains filtered or unexported fields
}

func NewAuthMiddleware

func NewAuthMiddleware(logger logger.LoggerInterface, options ...AuthMiddlewareOptions) *AuthMiddleware

New constructs a new Secure instance with supplied options.

func (*AuthMiddleware) CheckJWT

func (m *AuthMiddleware) CheckJWT(w http.ResponseWriter, r *http.Request) error

func (*AuthMiddleware) Handler

func (m *AuthMiddleware) Handler(h http.Handler) http.Handler

type AuthMiddlewareOptions

type AuthMiddlewareOptions struct {
	// The function that will return the Key to validate the JWT.
	// It can be either a shared secret or a public key.
	// Default value: nil
	ValidationKeyGetter jwt.Keyfunc
	// The name of the property in the request where the user information
	// from the JWT will be stored.
	// Default value: "user"
	UserProperty string
	// The function that will be called when there's an error validating the token
	// Default value:
	ErrorHandler errorHandler
	// A boolean indicating if the credentials are required or not
	// Default value: false
	CredentialsOptional bool
	// A function that extracts the token from the request
	// Default: FromAuthHeader (i.e., from Authorization header as bearer token)
	Extractor TokenExtractor
	// Debug flag turns on debugging output
	// Default: false
	Debug bool
	// When set, all requests with the OPTIONS method will use authentication
	// Default: false
	EnableAuthOnOptions bool
	// When set, the middelware verifies that tokens are signed with the specific signing algorithm
	// If the signing method is not constant the ValidationKeyGetter callback can be used to implement additional checks
	// Important to avoid securlty issues described here: https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/
	// Default: nil
	SigningMethod jwt.SigningMethod
}

Options is a struct for specifying configuration options for the middleware.

type OauthHandler

type OauthHandler struct {
	// contains filtered or unexported fields
}

func NewServer

func NewServer(ctx context.Context, logger logger.LoggerInterface, serverTypeName string, ac *openId.AuthCfg) (s *OauthHandler, err error)

create a new back end server with appropriate auth

func (*OauthHandler) Handler

func (s *OauthHandler) Handler(h http.Handler) (h2 http.Handler)

Add the auth middleware to the handler stack

type TokenExtractor

type TokenExtractor func(r *http.Request) (string, error)

TokenExtractor is a function that takes a request as input and returns either a token or an error. An error should only be returned if an attempt to specify a token was found, but the information was somehow incorrectly formed. In the case where a token is simply not present, this should not be treated as an error. An empty string should be returned in that case.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL