Skip to content

Commit ffe1032

Browse files
committed
feat: handle token exchange for local dex tokens
1 parent e558398 commit ffe1032

2 files changed

Lines changed: 79 additions & 17 deletions

File tree

.vscode/launch.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"name": "Dex",
9+
"type": "go",
10+
"request": "launch",
11+
"mode": "auto",
12+
"program": "./cmd/dex/",
13+
"args": ["serve", "/Users/sabithks/src/github.com/dexidp/dex/config.dev.yaml"]
14+
}
15+
]
16+
}

server/handlers.go

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,23 +1460,69 @@ func (s *Server) handleTokenExchange(w http.ResponseWriter, r *http.Request, cli
14601460
return
14611461
}
14621462

1463-
conn, err := s.getConnector(ctx, connID)
1464-
if err != nil {
1465-
s.logger.ErrorContext(r.Context(), "failed to get connector", "err", err)
1466-
s.tokenErrHelper(w, errInvalidRequest, "Requested connector does not exist.", http.StatusBadRequest)
1467-
return
1468-
}
1469-
teConn, ok := conn.Connector.(connector.TokenIdentityConnector)
1470-
if !ok {
1471-
s.logger.ErrorContext(r.Context(), "connector doesn't implement token exchange", "connector_id", connID)
1472-
s.tokenErrHelper(w, errInvalidRequest, "Requested connector does not exist.", http.StatusBadRequest)
1473-
return
1474-
}
1475-
identity, err := teConn.TokenIdentity(ctx, subjectTokenType, subjectToken)
1476-
if err != nil {
1477-
s.logger.ErrorContext(r.Context(), "failed to verify subject token", "err", err)
1478-
s.tokenErrHelper(w, errAccessDenied, "", http.StatusUnauthorized)
1479-
return
1463+
var err error
1464+
var identity connector.Identity
1465+
if connID == "local" || connID == "" {
1466+
// Verify local Dex token
1467+
verifier := oidc.NewVerifier(s.issuerURL.String(), &signerKeySet{s.signer}, &oidc.Config{SkipClientIDCheck: true})
1468+
idToken, err := verifier.Verify(ctx, subjectToken)
1469+
if err != nil {
1470+
s.logger.ErrorContext(r.Context(), "failed to verify local subject token", "err", err)
1471+
s.tokenErrHelper(w, errAccessDenied, "Invalid subject token.", http.StatusUnauthorized)
1472+
return
1473+
}
1474+
1475+
var claims idTokenClaims
1476+
if err := idToken.Claims(&claims); err != nil {
1477+
s.logger.ErrorContext(r.Context(), "failed to decode ID token claims", "err", err)
1478+
s.tokenErrHelper(w, errServerError, "Invalid subject token claims.", http.StatusInternalServerError)
1479+
return
1480+
}
1481+
1482+
var sub internal.IDTokenSubject
1483+
if err := internal.Unmarshal(claims.Subject, &sub); err != nil {
1484+
s.logger.ErrorContext(r.Context(), "failed to unmarshal subject", "err", err)
1485+
s.tokenErrHelper(w, errServerError, "Invalid subject format.", http.StatusInternalServerError)
1486+
return
1487+
}
1488+
1489+
if connID == "" {
1490+
connID = sub.ConnId
1491+
}
1492+
1493+
emailVerified := false
1494+
if claims.EmailVerified != nil {
1495+
emailVerified = *claims.EmailVerified
1496+
}
1497+
1498+
identity = connector.Identity{
1499+
UserID: sub.UserId,
1500+
Username: claims.Name,
1501+
PreferredUsername: claims.PreferredUsername,
1502+
Email: claims.Email,
1503+
EmailVerified: emailVerified,
1504+
Groups: claims.Groups,
1505+
}
1506+
} else {
1507+
conn, err := s.getConnector(ctx, connID)
1508+
if err != nil {
1509+
s.logger.ErrorContext(r.Context(), "failed to get connector", "err", err)
1510+
s.tokenErrHelper(w, errInvalidRequest, "Requested connector does not exist.", http.StatusBadRequest)
1511+
return
1512+
}
1513+
teConn, ok := conn.Connector.(connector.TokenIdentityConnector)
1514+
if !ok {
1515+
s.logger.ErrorContext(r.Context(), "connector doesn't implement token exchange", "connector_id", connID)
1516+
s.tokenErrHelper(w, errInvalidRequest, "Requested connector does not exist.", http.StatusBadRequest)
1517+
return
1518+
}
1519+
1520+
identity, err = teConn.TokenIdentity(ctx, subjectTokenType, subjectToken)
1521+
if err != nil {
1522+
s.logger.ErrorContext(r.Context(), "failed to verify subject token", "err", err)
1523+
s.tokenErrHelper(w, errAccessDenied, "", http.StatusUnauthorized)
1524+
return
1525+
}
14801526
}
14811527

14821528
claims := storage.Claims{

0 commit comments

Comments
 (0)