github.com/hashicorp/cap@v0.6.0/oidc/examples/spa/request_cache.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package main 5 6 import ( 7 "context" 8 "fmt" 9 "sync" 10 11 "github.com/hashicorp/cap/oidc" 12 ) 13 14 type extendedRequest struct { 15 oidc.Request 16 t oidc.Token 17 } 18 19 type requestCache struct { 20 m sync.Mutex 21 c map[string]extendedRequest 22 } 23 24 func newRequestCache() *requestCache { 25 return &requestCache{ 26 c: map[string]extendedRequest{}, 27 } 28 } 29 30 // Read implements the callback.StateReader interface and will delete the state 31 // before returning. 32 func (rc *requestCache) Read(ctx context.Context, state string) (oidc.Request, error) { 33 const op = "requestCache.Read" 34 rc.m.Lock() 35 defer rc.m.Unlock() 36 if oidcRequest, ok := rc.c[state]; ok { 37 if oidcRequest.IsExpired() { 38 delete(rc.c, state) 39 return nil, fmt.Errorf("%s: state %s not found", op, state) 40 } 41 return oidcRequest, nil 42 } 43 return nil, fmt.Errorf("%s: state %s not found", op, state) 44 } 45 46 func (rc *requestCache) Add(s oidc.Request) { 47 rc.m.Lock() 48 defer rc.m.Unlock() 49 rc.c[s.State()] = extendedRequest{Request: s} 50 } 51 52 func (rc *requestCache) SetToken(id string, t oidc.Token) error { 53 const op = "stateCache.SetToken" 54 rc.m.Lock() 55 defer rc.m.Unlock() 56 if oidcRequest, ok := rc.c[id]; ok { 57 if oidcRequest.IsExpired() { 58 delete(rc.c, id) 59 return fmt.Errorf("%s: state %s not found (expired)", op, id) 60 } 61 rc.c[id] = extendedRequest{Request: oidcRequest.Request, t: t} 62 return nil 63 } 64 return fmt.Errorf("%s: %s not found", op, id) 65 } 66 67 func (rc *requestCache) Delete(id string) { 68 rc.m.Lock() 69 defer rc.m.Unlock() 70 delete(rc.c, id) 71 }