From ee9a1cfc1cacb3f1ea4e3638e6d0f409457a152c Mon Sep 17 00:00:00 2001 From: Arlandis Word Date: Fri, 18 Mar 2022 17:23:13 -0400 Subject: [PATCH] allows config for leeway of 'nbf' and 'exp' This change lets clients decide how much leeway should apply to the 'exp' and 'nbf' claims coming from the JWTs on inbound requests. It's a pass-through to the jwt library's functionality. See https://github.com/golang-jwt/jwt/commit/d489c99d3e8a82bd47dcb3e4880414f7f747eaa7 for related changes there. --- connector/auth/jwt_token_validation.go | 18 ++++++++++++++++-- core/bot_framework_adapter.go | 9 ++++++++- go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/connector/auth/jwt_token_validation.go b/connector/auth/jwt_token_validation.go index eb573a8..bc83728 100644 --- a/connector/auth/jwt_token_validation.go +++ b/connector/auth/jwt_token_validation.go @@ -61,11 +61,25 @@ type TokenValidator interface { // JwtTokenValidator is the default implementation of TokenValidator. type JwtTokenValidator struct { cache.AuthCache + jwtoptions *JWTOptions } // NewJwtTokenValidator returns a new TokenValidator value with an empty cache func NewJwtTokenValidator() TokenValidator { - return &JwtTokenValidator{cache.AuthCache{}} + return &JwtTokenValidator{cache.AuthCache{}, &JWTOptions{}} +} + +type JWTOptions struct { + // Leeway is used to extend the allowance window + // for the "nbf" and "exp" claims of the token, + // allowing clients to loosen restrictions on *when* a token becomes valid + // and when it's considered expired + Leeway time.Duration +} + +// NewJwtTokenValidatorWithOptions returns a new TokenValidator value with JWT-options configured +func NewJwtTokenValidatorWithOptions(options *JWTOptions) TokenValidator { + return &JwtTokenValidator{cache.AuthCache{}, options} } // AuthenticateRequest authenticates the received request from connector service. @@ -143,7 +157,7 @@ func (jv *JwtTokenValidator) getIdentity(jwtString string) (ClaimsIdentity, erro } // TODO: Add options verify_aud and verify_exp - token, err := jwt.Parse(jwtString, getKey) + token, err := jwt.Parse(jwtString, getKey, jwt.WithLeeway(jv.jwtoptions.Leeway)) if err != nil { return nil, err } diff --git a/core/bot_framework_adapter.go b/core/bot_framework_adapter.go index 8d8a77c..dc6780d 100644 --- a/core/bot_framework_adapter.go +++ b/core/bot_framework_adapter.go @@ -52,6 +52,7 @@ type AdapterSetting struct { CredentialProvider auth.CredentialProvider AuthClient *http.Client ReplyClient *http.Client + JWTConfig *auth.JWTOptions } // BotFrameworkAdapter implements Adapter and is currently the only implementation returned to the user program. @@ -87,12 +88,18 @@ func NewBotAdapter(settings AdapterSetting) (Adapter, error) { clientConfig.ReplyClient = settings.ReplyClient } + var tokenValidator auth.TokenValidator + if settings.JWTConfig != nil { + tokenValidator = auth.NewJwtTokenValidatorWithOptions(settings.JWTConfig) + } else { + tokenValidator = auth.NewJwtTokenValidator() + } connectorClient, err := client.NewClient(clientConfig) if err != nil { return nil, errors.Wrap(err, "Failed to create Connector Client.") } - return &BotFrameworkAdapter{settings, auth.NewJwtTokenValidator(), connectorClient}, nil + return &BotFrameworkAdapter{settings, tokenValidator, connectorClient}, nil } // ProcessActivity receives an activity, processes it as specified in by the 'handler' and diff --git a/go.mod b/go.mod index c6874f0..2bdac7a 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/infracloudio/msbotbuilder-go go 1.16 require ( - github.com/golang-jwt/jwt/v4 v4.1.0 + github.com/golang-jwt/jwt/v4 v4.4.0 github.com/lestrrat-go/jwx v1.1.7 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.7.0 diff --git a/go.sum b/go.sum index aa223c4..761cd8c 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0 h1:sgNeV1VRMDzs6rzyPpxyM0jp317h github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0/go.mod h1:J70FGZSbzsjecRTiTzER+3f1KZLNaXkuv+yeFTKoxM8= github.com/goccy/go-json v0.4.8 h1:TfwOxfSp8hXH+ivoOk36RyDNmXATUETRdaNWDaZglf8= github.com/goccy/go-json v0.4.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0= -github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.4.0 h1:EmVIxB5jzbllGIjiCV5JG4VylbK3KE400tLGLI1cdfU= +github.com/golang-jwt/jwt/v4 v4.4.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/lestrrat-go/backoff/v2 v2.0.7 h1:i2SeK33aOFJlUNJZzf2IpXRBvqBBnaGXfY5Xaop/GsE= github.com/lestrrat-go/backoff/v2 v2.0.7/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y= github.com/lestrrat-go/blackmagic v1.0.0 h1:XzdxDbuQTz0RZZEmdU7cnQxUtFUzgCSPq8RCz4BxIi4=