11package oauth2
22
3- import "github.com/go-jose/go-jose/v3/jwt"
3+ import (
4+ "encoding/json"
5+ "net/http"
6+ "time"
7+
8+ "github.com/go-jose/go-jose/v3"
9+ "github.com/go-jose/go-jose/v3/jwt"
10+ "github.com/pkg/errors"
11+ )
412
513func UnsafeParseJWT (token string ) (* jwt.JSONWebToken , map [string ]interface {}, error ) {
614 var (
@@ -19,3 +27,111 @@ func UnsafeParseJWT(token string) (*jwt.JSONWebToken, map[string]interface{}, er
1927
2028 return t , claims , nil
2129}
30+
31+ type SignerProvider func () (jose.Signer , interface {}, error )
32+
33+ func JWKSigner (clientConfig ClientConfig , hc * http.Client ) SignerProvider {
34+ return func () (signer jose.Signer , _ interface {}, err error ) {
35+ var key jose.JSONWebKey
36+
37+ if clientConfig .SigningKey == "" {
38+ return nil , nil , errors .New ("no signing key path" )
39+ }
40+
41+ if key , err = ReadKey (SigningKey , clientConfig .SigningKey , hc ); err != nil {
42+ return nil , nil , errors .Wrapf (err , "failed to read signing key from %s" , clientConfig .SigningKey )
43+ }
44+
45+ if signer , err = jose .NewSigner (jose.SigningKey {
46+ Algorithm : jose .SignatureAlgorithm (key .Algorithm ),
47+ Key : key .Key ,
48+ }, & jose.SignerOptions {
49+ ExtraHeaders : map [jose.HeaderKey ]interface {}{"kid" : key .KeyID },
50+ }); err != nil {
51+ return nil , nil , errors .Wrapf (err , "failed to create a signer" )
52+ }
53+
54+ return signer , key .Key , nil
55+ }
56+ }
57+
58+ func SecretSigner (secret []byte ) SignerProvider {
59+ return func () (jose.Signer , interface {}, error ) {
60+ signer , err := jose .NewSigner (jose.SigningKey {
61+ Algorithm : jose .HS256 ,
62+ Key : secret ,
63+ }, nil )
64+
65+ return signer , secret , err
66+ }
67+ }
68+
69+ type ClaimsProvider func () (map [string ]interface {}, error )
70+
71+ func AssertionClaims (serverConfig ServerConfig , clientConfig ClientConfig ) ClaimsProvider {
72+ return func () (map [string ]interface {}, error ) {
73+ var err error
74+
75+ claims := map [string ]interface {}{
76+ "iss" : serverConfig .TokenEndpoint ,
77+ "aud" : serverConfig .TokenEndpoint ,
78+ "iat" : time .Now ().Unix (),
79+ "exp" : time .Now ().Add (time .Minute * 10 ).Unix (),
80+ "jti" : RandomString (20 ),
81+ }
82+
83+ if clientConfig .Assertion == "" {
84+ clientConfig .Assertion = "{}"
85+ }
86+
87+ if err = json .Unmarshal ([]byte (clientConfig .Assertion ), & claims ); err != nil {
88+ return nil , err
89+ }
90+
91+ return claims , nil
92+ }
93+ }
94+
95+ func ClientAssertionClaims (serverConfig ServerConfig , clientConfig ClientConfig ) ClaimsProvider {
96+ return func () (map [string ]interface {}, error ) {
97+ return map [string ]interface {}{
98+ "iss" : clientConfig .ClientID ,
99+ "sub" : clientConfig .ClientID ,
100+ "aud" : serverConfig .TokenEndpoint ,
101+ "iat" : time .Now ().Unix (),
102+ "exp" : time .Now ().Add (time .Minute * 10 ).Unix (),
103+ "jti" : RandomString (20 ),
104+ }, nil
105+ }
106+ }
107+
108+ func SignJWT (claimsProvider ClaimsProvider , signerProvider SignerProvider ) (jwt string , key interface {}, err error ) {
109+ var (
110+ signer jose.Signer
111+ claims map [string ]interface {}
112+ jws * jose.JSONWebSignature
113+ bs []byte
114+ )
115+
116+ if signer , key , err = signerProvider (); err != nil {
117+ return "" , nil , errors .Wrapf (err , "failed to create signer" )
118+ }
119+
120+ if claims , err = claimsProvider (); err != nil {
121+ return "" , nil , errors .Wrapf (err , "failed to build claims" )
122+ }
123+
124+ if bs , err = json .Marshal (claims ); err != nil {
125+ return "" , nil , errors .Wrapf (err , "failed to serialize claims" )
126+ }
127+
128+ if jws , err = signer .Sign (bs ); err != nil {
129+ return "" , nil , errors .Wrapf (err , "failed to sign jwt" )
130+ }
131+
132+ if jwt , err = jws .CompactSerialize (); err != nil {
133+ return "" , nil , err
134+ }
135+
136+ return jwt , key , nil
137+ }
0 commit comments