This repository was archived by the owner on Aug 17, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgoogle_id.go
More file actions
97 lines (85 loc) · 2.99 KB
/
google_id.go
File metadata and controls
97 lines (85 loc) · 2.99 KB
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
85
86
87
88
89
90
91
92
93
94
95
96
97
package oauth2
import (
"context"
"strconv"
"strings"
"github.com/coreos/go-oidc/v3/oidc"
"impractical.co/googleid"
yall "yall.in"
"lockbox.dev/accounts"
"lockbox.dev/grants"
)
// googleIDGranter fills the granter interface for exchanging
// a Google ID token for a Grant.
type googleIDGranter struct {
tokenVal string // the token
client string // the client that created the token
gClients []string // the Google clients that the token must be for
oidcVerifier *oidc.IDTokenVerifier // the verifier that we can use to verify tokens
accounts accounts.Storer // the Storer that grants access to accounts data
// set by Validate and here so Grant can use them
account accounts.Account
token *googleid.Token
}
// Validate checks that the ID token is actually valid and should
// be considered proof of identity.
func (g *googleIDGranter) Validate(ctx context.Context) APIError {
token, err := googleid.Decode(g.tokenVal)
if err != nil {
yall.FromContext(ctx).WithError(err).Debug("Error decoding ID token")
return invalidGrantError
}
err = googleid.Verify(ctx, g.tokenVal, g.gClients, g.oidcVerifier)
if err != nil {
yall.FromContext(ctx).WithError(err).Debug("Error verifying ID token")
return invalidGrantError
}
g.token = token
account, err := g.accounts.Get(ctx, strings.ToLower(token.Email))
if err != nil {
yall.FromContext(ctx).WithError(err).WithField("email", token.Email).Error("Error retrieving account")
return serverError
}
g.account = account
return APIError{}
}
// ProfileID returns the ID of the profile the grant is for. It must be called
// after Validate.
func (g *googleIDGranter) ProfileID(_ context.Context) string {
return g.account.ProfileID
}
// AccountID returns the ID of the account the grant is for. It must be called
// after Validate.
func (g *googleIDGranter) AccountID(_ context.Context) string {
return g.account.ID
}
// Grant returns a Grant populated with the appropriate values for
// a Google ID Token-generated Grant.
func (g *googleIDGranter) Grant(_ context.Context, scopes []string) grants.Grant {
intBase := 10
return grants.Grant{
SourceType: "google_id",
SourceID: g.token.Iss + ";" + g.token.Sub + ";" + strconv.FormatInt(g.token.Iat, intBase),
AccountID: g.account.ID,
ProfileID: g.account.ProfileID,
ClientID: g.client,
Scopes: scopes,
Used: false,
}
}
// Granted does nothing, we rely on SourceID to keep from issuing
// duplicate grants for the same token.
func (*googleIDGranter) Granted(_ context.Context) error {
return nil
}
// Redirects returns false, indicating we want to use the JSON request/response
// flow, not the URL querystring redirect flow.
func (*googleIDGranter) Redirects() bool {
return false
}
// CreatesGrantsInline reports that `googleIDGranter` creates Grants inline in
// the token endpoint, they don't need to be pre-created using the authorize
// endpoint.
func (*googleIDGranter) CreatesGrantsInline() bool {
return true
}