forked from oxisto/gcp-jwt-go
/
token.go
84 lines (71 loc) · 2.25 KB
/
token.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package oauth2
// Based on https://github.com/golang/oauth2/blob/master/google/jwt.go
import (
"context"
"fmt"
"strings"
"time"
"github.com/dgrijalva/jwt-go"
"golang.org/x/oauth2"
"github.com/someone1/gcp-jwt-go"
)
// JWTAccessTokenSource returns a TokenSource that uses the IAM API to sign tokens.
// This is meant as a helper for situations in which you want to authenticate calls
// using the configured service account and does not actually perform an Oauth flow.
// This can be useful in service to service communications for user-defined APIs.
// The audience is typically a URL that specifies the scope of the credentials or the
// API endpoint.
//
// Complimentary to https://github.com/someone1/gcp-jwt-go/jwtmiddleware
func JWTAccessTokenSource(ctx context.Context, config *gcpjwt.IAMConfig, audience string) (oauth2.TokenSource, error) {
ctx = gcpjwt.NewIAMContext(ctx, config)
ts := &jwtAccessTokenSource{
ctx: ctx,
audience: audience,
jwtConfig: config,
}
tok, err := ts.Token()
if err != nil {
return nil, err
}
return oauth2.ReuseTokenSource(tok, ts), nil
}
type jwtAccessTokenSource struct {
ctx context.Context
audience string
jwtConfig *gcpjwt.IAMConfig
}
func (ts *jwtAccessTokenSource) Token() (*oauth2.Token, error) {
iat := time.Now()
exp := iat.Add(time.Hour)
claims := &jwt.StandardClaims{
Issuer: ts.jwtConfig.ServiceAccount,
Subject: ts.jwtConfig.ServiceAccount,
IssuedAt: iat.Unix(),
NotBefore: iat.Unix(),
ExpiresAt: exp.Unix(),
Audience: ts.audience,
}
var token *jwt.Token
switch ts.jwtConfig.IAMType {
case gcpjwt.IAMBlobType:
token = jwt.New(gcpjwt.SigningMethodIAMBlob)
case gcpjwt.IAMJwtType:
token = jwt.New(gcpjwt.SigningMethodIAMJWT)
default:
return nil, fmt.Errorf("gcpjwt/oauth2: unknown token type `%v` provided", ts.jwtConfig.IAMType)
}
token.Claims = claims
signingString, err := token.SigningString()
if err != nil {
return nil, err
}
at, err := token.Method.Sign(signingString, ts.ctx)
if err != nil {
return nil, fmt.Errorf("gcpjwt/oauth2: could not sign JWT: %v", err)
}
if ts.jwtConfig.IAMType == gcpjwt.IAMBlobType {
at = strings.Join([]string{signingString, at}, ".")
}
return &oauth2.Token{AccessToken: at, TokenType: "Bearer", Expiry: exp}, nil
}