github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/auth/token/context.go (about) 1 package token 2 3 import ( 4 "context" 5 "net/http" 6 "strings" 7 ) 8 9 // CtxKey defines a distinct type for context keys used by the access 10 // package 11 type CtxKey string 12 13 // tokenCtxKey is the key for adding an access token to a context.Context 14 const tokenCtxKey CtxKey = "Token" 15 16 // AddToContext adds a token string to a context 17 func AddToContext(ctx context.Context, s string) context.Context { 18 return context.WithValue(ctx, tokenCtxKey, s) 19 } 20 21 // FromCtx extracts the JWT from a given 22 // context if one is set, returning nil otherwise 23 func FromCtx(ctx context.Context) string { 24 iface := ctx.Value(tokenCtxKey) 25 if s, ok := iface.(string); ok { 26 return s 27 } 28 return "" 29 } 30 31 const ( 32 // httpAuthorizationHeader is the http header field to check for tokens, 33 // follows OAuth 2.0 spec 34 httpAuthorizationHeader = "authorization" 35 // httpAuthorizationBearerPrefix is a prefix before a token in the 36 // Authorization header field. Follows OAuth 2.0 spec 37 httpAuthorizationBearerPrefix = "Bearer " 38 ) 39 40 // OAuthTokenMiddleware parses any "authorization" header containing a Bearer 41 // token & adds it to the request context 42 func OAuthTokenMiddleware(next http.Handler) http.Handler { 43 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 44 reqToken := r.Header.Get(httpAuthorizationHeader) 45 if reqToken == "" && r.FormValue(httpAuthorizationHeader) != "" { 46 reqToken = r.FormValue(httpAuthorizationHeader) 47 } 48 if reqToken == "" { 49 next.ServeHTTP(w, r) 50 return 51 } 52 53 if !strings.HasPrefix(reqToken, httpAuthorizationBearerPrefix) { 54 next.ServeHTTP(w, r) 55 return 56 } 57 58 tokenStr := strings.TrimPrefix(reqToken, httpAuthorizationBearerPrefix) 59 ctx := AddToContext(r.Context(), tokenStr) 60 61 r = r.WithContext(ctx) 62 next.ServeHTTP(w, r) 63 }) 64 } 65 66 // AddContextTokenToRequest checks the supplied context for an auth token and 67 // adds it to an http request, returns true if a token is added 68 func AddContextTokenToRequest(ctx context.Context, r *http.Request) (*http.Request, bool) { 69 if s := FromCtx(ctx); s != "" { 70 r.Header.Set(httpAuthorizationHeader, strings.Join([]string{httpAuthorizationBearerPrefix, s}, "")) 71 return r, true 72 } 73 return r, false 74 }