github.com/blend/go-sdk@v1.20220411.3/web/jwt_manager.go (about) 1 /* 2 3 Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file. 5 6 */ 7 8 package web 9 10 import ( 11 "context" 12 "time" 13 14 "github.com/golang-jwt/jwt" 15 16 "github.com/blend/go-sdk/ex" 17 ) 18 19 const ( 20 // ErrJWTNonstandardClaims can be returned by the jwt manager keyfunc. 21 ErrJWTNonstandardClaims = ex.Class("jwt; invalid claims object; should be standard claims") 22 ) 23 24 // NewJWTManager returns a new jwt manager from a key. 25 func NewJWTManager(key []byte) *JWTManager { 26 return &JWTManager{ 27 KeyProvider: func(_ *Session) ([]byte, error) { 28 return key, nil 29 }, 30 } 31 } 32 33 // JWTManager is a manager for JWTs. 34 type JWTManager struct { 35 KeyProvider func(*Session) ([]byte, error) 36 } 37 38 // Apply applies the jwtm to the given auth manager. 39 func (jwtm JWTManager) Apply(am *AuthManager) { 40 am.SerializeHandler = jwtm.SerializeHandler 41 am.FetchHandler = jwtm.FetchHandler 42 } 43 44 // 45 // auth manager hooks 46 // 47 48 // SerializeHandler is a shim to the auth manager. 49 func (jwtm JWTManager) SerializeHandler(_ context.Context, session *Session) (output string, err error) { 50 var key []byte 51 key, err = jwtm.KeyProvider(session) 52 if err != nil { 53 return 54 } 55 56 token := jwt.NewWithClaims(jwt.SigningMethodHS512, jwtm.Claims(session)) 57 output, err = token.SignedString(key) 58 return 59 } 60 61 // FetchHandler is a shim to the auth manager. 62 func (jwtm JWTManager) FetchHandler(_ context.Context, sessionValue string) (*Session, error) { 63 var claims jwt.StandardClaims 64 _, err := jwt.ParseWithClaims(sessionValue, &claims, jwtm.KeyFunc) 65 if err != nil { 66 return nil, err 67 } 68 69 // do we check if the token is valid ??? 70 return jwtm.FromClaims(&claims), nil 71 } 72 73 // 74 // utility functions 75 // 76 77 // Claims returns the sesion as a JWT standard claims object. 78 func (jwtm JWTManager) Claims(session *Session) *jwt.StandardClaims { 79 return &jwt.StandardClaims{ 80 Id: session.SessionID, 81 Audience: session.BaseURL, 82 Issuer: "go-web", 83 Subject: session.UserID, 84 IssuedAt: session.CreatedUTC.Unix(), 85 ExpiresAt: session.ExpiresUTC.Unix(), 86 } 87 } 88 89 // FromClaims returns a session from a given claims set. 90 func (jwtm JWTManager) FromClaims(claims *jwt.StandardClaims) *Session { 91 return &Session{ 92 SessionID: claims.Id, 93 BaseURL: claims.Audience, 94 UserID: claims.Subject, 95 CreatedUTC: time.Unix(claims.IssuedAt, 0).In(time.UTC), 96 ExpiresUTC: time.Unix(claims.ExpiresAt, 0).In(time.UTC), 97 } 98 } 99 100 // KeyFunc is a shim function to get the key for a given token. 101 func (jwtm JWTManager) KeyFunc(token *jwt.Token) (interface{}, error) { 102 typed, ok := token.Claims.(*jwt.StandardClaims) 103 if !ok { 104 return nil, ErrJWTNonstandardClaims 105 } 106 return jwtm.KeyProvider(jwtm.FromClaims(typed)) 107 }