Skip to content

Commit 62951e3

Browse files
committed
feat: accept oidc token as authentication
1 parent b239cc3 commit 62951e3

File tree

4 files changed

+77
-1
lines changed

4 files changed

+77
-1
lines changed

internal/auth/providers/github.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ func (p *GitHubProvider) Exchange(redirectURI, code string) (*Identity, error) {
9696
}, nil
9797
}
9898

99+
func (p *GitHubProvider) ExchangeIDToken(rawIdToken string) (*Identity, error) {
100+
return nil, fmt.Errorf("unsupported operation")
101+
}
102+
103+
func (p *GitHubProvider) IsInteractive() bool {
104+
return true
105+
}
106+
99107
func (p *GitHubProvider) getTeams(ctx context.Context, client *github.Client) ([]string, error) {
100108
var result []string
101109
var page = 0

internal/auth/providers/oidc.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func NewOIDCProvider(c *config.Provider) (*OIDCProvider, error) {
2525
return nil, err
2626
}
2727

28-
verifier := provider.Verifier(&oidc.Config{ClientID: c.ClientID})
28+
verifier := provider.Verifier(&oidc.Config{ClientID: c.ClientID, SkipClientIDCheck: c.ClientID == ""})
2929

3030
return &OIDCProvider{
3131
clientID: c.ClientID,
@@ -48,6 +48,29 @@ func (p *OIDCProvider) GetLoginURL(redirectURI, state string) string {
4848
return oauth2Config.AuthCodeURL(state)
4949
}
5050

51+
func (p *OIDCProvider) ExchangeIDToken(rawIdToken string) (*Identity, error) {
52+
// Parse and verify ID Token payload.
53+
idToken, err := p.verifier.Verify(context.Background(), rawIdToken)
54+
if err != nil {
55+
return nil, err
56+
}
57+
58+
sub, email, name, tokenClaims, err := p.getTokenClaims(idToken)
59+
if err != nil {
60+
return nil, err
61+
}
62+
63+
return &Identity{
64+
UserID: sub,
65+
Username: name,
66+
Email: email,
67+
Attr: map[string]interface{}{
68+
"provider": "oidc",
69+
"token": tokenClaims,
70+
},
71+
}, nil
72+
}
73+
5174
func (p *OIDCProvider) Exchange(redirectURI, code string) (*Identity, error) {
5275
oauth2Config := oauth2.Config{
5376
ClientID: p.clientID,
@@ -97,6 +120,10 @@ func (p *OIDCProvider) Exchange(redirectURI, code string) (*Identity, error) {
97120
}, nil
98121
}
99122

123+
func (p *OIDCProvider) IsInteractive() bool {
124+
return p.provider.Endpoint().AuthURL != ""
125+
}
126+
100127
func (p *OIDCProvider) getTokenClaims(idToken *oidc.IDToken) (string, string, string, map[string]interface{}, error) {
101128
var raw = make(map[string]interface{})
102129
var claims struct {

internal/auth/providers/providers.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ func NewProvider(c *config.Provider) (AuthProvider, error) {
1919
type AuthProvider interface {
2020
GetLoginURL(redirectURI, state string) string
2121
Exchange(redirectURI, code string) (*Identity, error)
22+
ExchangeIDToken(rawIdToken string) (*Identity, error)
23+
IsInteractive() bool
2224
}
2325

2426
type Identity struct {

internal/auth/server.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,45 @@ func (s *Server) RegisterSession(req *api.RegisterSessionRequest) (*api.SessionT
156156

157157
return &response, nil
158158
}
159+
160+
identity, err := s.provider.ExchangeIDToken(req.AuthToken)
161+
if err == nil {
162+
authorized, roles, err := s.evaluatePolicies(req.Policies, identity)
163+
if err != nil {
164+
return nil, err
165+
}
166+
167+
if !authorized {
168+
return nil, echo.NewHTTPError(http.StatusUnauthorized)
169+
}
170+
171+
st := api.SessionToken{
172+
UserID: identity.UserID,
173+
Username: identity.Username,
174+
Email: identity.Email,
175+
Roles: roles,
176+
Target: req.Target,
177+
ExpirationTime: now.Add(5 * time.Minute).UTC(),
178+
Checksum: req.Checksum,
179+
}
180+
181+
sessionToken, err := s.privateKey.SealBase58(*publicKey, st)
182+
if err != nil {
183+
return nil, err
184+
}
185+
186+
response := api.SessionTokenResponse{
187+
SessionId: req.SessionId,
188+
SessionToken: sessionToken,
189+
AuthToken: req.AuthToken,
190+
}
191+
192+
return &response, nil
193+
}
194+
}
195+
196+
if !s.provider.IsInteractive() {
197+
return nil, echo.NewHTTPError(http.StatusUnauthorized)
159198
}
160199

161200
if err := s.sessions.Set(req.SessionId, &session{PublicKey: *publicKey, Policies: req.Policies, Target: req.Target, Checksum: req.Checksum}); err != nil {

0 commit comments

Comments
 (0)