Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the Locale claim for the OIDC connector #1535

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
bin
dist
_output
.idea
.DS_Store
4 changes: 2 additions & 2 deletions connector/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ type Identity struct {
Username string
Email string
EmailVerified bool

Groups []string
Groups []string
Locale string

// ConnectorData holds data used by the connector for subsequent requests after initial
// authentication, such as access tokens for upstream provides.
Expand Down
3 changes: 3 additions & 0 deletions connector/oidc/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,11 +259,14 @@ func (c *oidcConnector) HandleCallback(s connector.Scopes, r *http.Request) (ide
}
}

locale, _ := claims["locale"].(string)
justin-slowik marked this conversation as resolved.
Show resolved Hide resolved

identity = connector.Identity{
UserID: idToken.Subject,
Username: name,
Email: email,
EmailVerified: emailVerified,
Locale: locale,
}

if c.userIDKey != "" {
Expand Down
3 changes: 3 additions & 0 deletions server/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ func (s *Server) finalizeLogin(identity connector.Identity, authReq storage.Auth
Email: identity.Email,
EmailVerified: identity.EmailVerified,
Groups: identity.Groups,
Locale: identity.Locale,
}

updater := func(a storage.AuthRequest) (storage.AuthRequest, error) {
Expand Down Expand Up @@ -974,6 +975,7 @@ func (s *Server) handleRefreshToken(w http.ResponseWriter, r *http.Request, clie
EmailVerified: refresh.Claims.EmailVerified,
Groups: refresh.Claims.Groups,
ConnectorData: refresh.ConnectorData,
Locale: refresh.Claims.Locale,
}

// Can the connector refresh the identity? If so, attempt to refresh the data
Expand All @@ -997,6 +999,7 @@ func (s *Server) handleRefreshToken(w http.ResponseWriter, r *http.Request, clie
Email: ident.Email,
EmailVerified: ident.EmailVerified,
Groups: ident.Groups,
Locale: ident.Locale,
}

accessToken, err := s.newAccessToken(client.ID, claims, scopes, refresh.Nonce, refresh.ConnectorID)
Expand Down
9 changes: 5 additions & 4 deletions server/oauth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,10 @@ type idTokenClaims struct {

AccessTokenHash string `json:"at_hash,omitempty"`

Email string `json:"email,omitempty"`
EmailVerified *bool `json:"email_verified,omitempty"`

Groups []string `json:"groups,omitempty"`
Email string `json:"email,omitempty"`
EmailVerified *bool `json:"email_verified,omitempty"`
Groups []string `json:"groups,omitempty"`
Locale string `json:"locale,omitempty"`

Name string `json:"name,omitempty"`

Expand Down Expand Up @@ -329,6 +329,7 @@ func (s *Server) newIDToken(clientID string, claims storage.Claims, scopes []str
tok.Groups = claims.Groups
case scope == scopeProfile:
tok.Name = claims.Username
tok.Locale = claims.Locale
case scope == scopeFederatedID:
tok.FederatedIDClaims = &federatedIDClaims{
ConnectorID: connID,
Expand Down
8 changes: 8 additions & 0 deletions storage/conformance/conformance.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ func testAuthRequestCRUD(t *testing.T, s storage.Storage) {
Email: "[email protected]",
EmailVerified: true,
Groups: []string{"a", "b"},
Locale: "en_US",
justin-slowik marked this conversation as resolved.
Show resolved Hide resolved
},
}

Expand Down Expand Up @@ -130,6 +131,7 @@ func testAuthRequestCRUD(t *testing.T, s storage.Storage) {
Email: "[email protected]",
EmailVerified: true,
Groups: []string{"a"},
Locale: "en_US",
},
}

Expand Down Expand Up @@ -179,6 +181,7 @@ func testAuthCodeCRUD(t *testing.T, s storage.Storage) {
Email: "[email protected]",
EmailVerified: true,
Groups: []string{"a", "b"},
Locale: "en_US",
},
}

Expand All @@ -201,6 +204,7 @@ func testAuthCodeCRUD(t *testing.T, s storage.Storage) {
Email: "[email protected]",
EmailVerified: true,
Groups: []string{"a"},
Locale: "en_US",
},
}

Expand Down Expand Up @@ -322,6 +326,7 @@ func testRefreshTokenCRUD(t *testing.T, s storage.Storage) {
Email: "[email protected]",
EmailVerified: true,
Groups: []string{"a", "b"},
Locale: "en_US",
},
ConnectorData: []byte(`{"some":"data"}`),
}
Expand Down Expand Up @@ -376,6 +381,7 @@ func testRefreshTokenCRUD(t *testing.T, s storage.Storage) {
Email: "[email protected]",
EmailVerified: true,
Groups: []string{"a", "b"},
Locale: "en_US",
},
ConnectorData: []byte(`{"some":"data"}`),
}
Expand Down Expand Up @@ -795,6 +801,7 @@ func testGC(t *testing.T, s storage.Storage) {
Email: "[email protected]",
EmailVerified: true,
Groups: []string{"a", "b"},
Locale: "en_US",
},
}

Expand Down Expand Up @@ -855,6 +862,7 @@ func testTimezones(t *testing.T, s storage.Storage) {
Email: "[email protected]",
EmailVerified: true,
Groups: []string{"a", "b"},
Locale: "en_US",
},
}
if err := s.CreateAuthCode(c); err != nil {
Expand Down
3 changes: 3 additions & 0 deletions storage/etcd/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ type Claims struct {
Email string `json:"email"`
EmailVerified bool `json:"emailVerified"`
Groups []string `json:"groups,omitempty"`
Locale string `json:"locale,omitempty"`
}

func fromStorageClaims(i storage.Claims) Claims {
Expand All @@ -162,6 +163,7 @@ func fromStorageClaims(i storage.Claims) Claims {
Email: i.Email,
EmailVerified: i.EmailVerified,
Groups: i.Groups,
Locale: i.Locale,
}
}

Expand All @@ -172,6 +174,7 @@ func toStorageClaims(i Claims) storage.Claims {
Email: i.Email,
EmailVerified: i.EmailVerified,
Groups: i.Groups,
Locale: i.Locale,
}
}

Expand Down
3 changes: 3 additions & 0 deletions storage/kubernetes/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ type Claims struct {
Email string `json:"email"`
EmailVerified bool `json:"emailVerified"`
Groups []string `json:"groups,omitempty"`
Locale string `json:"locale,omitempty"`
}

func fromStorageClaims(i storage.Claims) Claims {
Expand All @@ -224,6 +225,7 @@ func fromStorageClaims(i storage.Claims) Claims {
Email: i.Email,
EmailVerified: i.EmailVerified,
Groups: i.Groups,
Locale: i.Locale,
}
}

Expand All @@ -234,6 +236,7 @@ func toStorageClaims(i Claims) storage.Claims {
Email: i.Email,
EmailVerified: i.EmailVerified,
Groups: i.Groups,
Locale: i.Locale,
}
}

Expand Down
56 changes: 29 additions & 27 deletions storage/sql/crud.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,18 @@ func (c *conn) CreateAuthRequest(a storage.AuthRequest) error {
id, client_id, response_types, scopes, redirect_uri, nonce, state,
force_approval_prompt, logged_in,
claims_user_id, claims_username, claims_email, claims_email_verified,
claims_groups,
claims_groups, claims_locale,
connector_id, connector_data,
expiry
)
values (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18
);
`,
a.ID, a.ClientID, encoder(a.ResponseTypes), encoder(a.Scopes), a.RedirectURI, a.Nonce, a.State,
a.ForceApprovalPrompt, a.LoggedIn,
a.Claims.UserID, a.Claims.Username, a.Claims.Email, a.Claims.EmailVerified,
encoder(a.Claims.Groups),
encoder(a.Claims.Groups), a.Claims.Locale,
a.ConnectorID, a.ConnectorData,
a.Expiry,
)
Expand Down Expand Up @@ -152,14 +152,15 @@ func (c *conn) UpdateAuthRequest(id string, updater func(a storage.AuthRequest)
claims_user_id = $9, claims_username = $10, claims_email = $11,
claims_email_verified = $12,
claims_groups = $13,
connector_id = $14, connector_data = $15,
expiry = $16
where id = $17;
claims_locale = $14,
justin-slowik marked this conversation as resolved.
Show resolved Hide resolved
connector_id = $15, connector_data = $16,
expiry = $17
where id = $18;
`,
a.ClientID, encoder(a.ResponseTypes), encoder(a.Scopes), a.RedirectURI, a.Nonce, a.State,
a.ForceApprovalPrompt, a.LoggedIn,
a.Claims.UserID, a.Claims.Username, a.Claims.Email, a.Claims.EmailVerified,
encoder(a.Claims.Groups),
encoder(a.Claims.Groups), a.Claims.Locale,
a.ConnectorID, a.ConnectorData,
a.Expiry, r.ID,
)
Expand All @@ -181,14 +182,14 @@ func getAuthRequest(q querier, id string) (a storage.AuthRequest, err error) {
id, client_id, response_types, scopes, redirect_uri, nonce, state,
force_approval_prompt, logged_in,
claims_user_id, claims_username, claims_email, claims_email_verified,
claims_groups,
claims_groups, claims_locale,
connector_id, connector_data, expiry
from auth_request where id = $1;
`, id).Scan(
&a.ID, &a.ClientID, decoder(&a.ResponseTypes), decoder(&a.Scopes), &a.RedirectURI, &a.Nonce, &a.State,
&a.ForceApprovalPrompt, &a.LoggedIn,
&a.Claims.UserID, &a.Claims.Username, &a.Claims.Email, &a.Claims.EmailVerified,
decoder(&a.Claims.Groups),
decoder(&a.Claims.Groups), &a.Claims.Locale,
&a.ConnectorID, &a.ConnectorData, &a.Expiry,
)
if err != nil {
Expand All @@ -205,15 +206,15 @@ func (c *conn) CreateAuthCode(a storage.AuthCode) error {
insert into auth_code (
id, client_id, scopes, nonce, redirect_uri,
claims_user_id, claims_username,
claims_email, claims_email_verified, claims_groups,
claims_email, claims_email_verified, claims_groups, claims_locale,
connector_id, connector_data,
expiry
)
values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13);
values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14);
`,
a.ID, a.ClientID, encoder(a.Scopes), a.Nonce, a.RedirectURI, a.Claims.UserID,
a.Claims.Username, a.Claims.Email, a.Claims.EmailVerified, encoder(a.Claims.Groups),
a.ConnectorID, a.ConnectorData, a.Expiry,
a.Claims.Locale, a.ConnectorID, a.ConnectorData, a.Expiry,
)

if err != nil {
Expand All @@ -231,13 +232,13 @@ func (c *conn) GetAuthCode(id string) (a storage.AuthCode, err error) {
id, client_id, scopes, nonce, redirect_uri,
claims_user_id, claims_username,
claims_email, claims_email_verified, claims_groups,
connector_id, connector_data,
claims_locale, connector_id, connector_data,
expiry
from auth_code where id = $1;
`, id).Scan(
&a.ID, &a.ClientID, decoder(&a.Scopes), &a.Nonce, &a.RedirectURI, &a.Claims.UserID,
&a.Claims.Username, &a.Claims.Email, &a.Claims.EmailVerified, decoder(&a.Claims.Groups),
&a.ConnectorID, &a.ConnectorData, &a.Expiry,
&a.Claims.Locale, &a.ConnectorID, &a.ConnectorData, &a.Expiry,
)
if err != nil {
if err == sql.ErrNoRows {
Expand All @@ -253,15 +254,15 @@ func (c *conn) CreateRefresh(r storage.RefreshToken) error {
insert into refresh_token (
id, client_id, scopes, nonce,
claims_user_id, claims_username, claims_email, claims_email_verified,
claims_groups,
claims_groups, claims_locale,
connector_id, connector_data,
token, created_at, last_used
)
values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14);
values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15);
`,
r.ID, r.ClientID, encoder(r.Scopes), r.Nonce,
r.Claims.UserID, r.Claims.Username, r.Claims.Email, r.Claims.EmailVerified,
encoder(r.Claims.Groups),
encoder(r.Claims.Groups), r.Claims.Locale,
r.ConnectorID, r.ConnectorData,
r.Token, r.CreatedAt, r.LastUsed,
)
Expand Down Expand Up @@ -294,17 +295,18 @@ func (c *conn) UpdateRefreshToken(id string, updater func(old storage.RefreshTok
claims_email = $6,
claims_email_verified = $7,
claims_groups = $8,
connector_id = $9,
connector_data = $10,
token = $11,
created_at = $12,
last_used = $13
claims_locale = $9,
connector_id = $10,
connector_data = $11,
token = $12,
created_at = $13,
last_used = $14
where
id = $14
id = $15
`,
r.ClientID, encoder(r.Scopes), r.Nonce,
r.Claims.UserID, r.Claims.Username, r.Claims.Email, r.Claims.EmailVerified,
encoder(r.Claims.Groups),
encoder(r.Claims.Groups), r.Claims.Locale,
r.ConnectorID, r.ConnectorData,
r.Token, r.CreatedAt, r.LastUsed, id,
)
Expand All @@ -324,7 +326,7 @@ func getRefresh(q querier, id string) (storage.RefreshToken, error) {
select
id, client_id, scopes, nonce,
claims_user_id, claims_username, claims_email, claims_email_verified,
claims_groups,
claims_groups, claims_locale,
connector_id, connector_data,
token, created_at, last_used
from refresh_token where id = $1;
Expand All @@ -336,7 +338,7 @@ func (c *conn) ListRefreshTokens() ([]storage.RefreshToken, error) {
select
id, client_id, scopes, nonce,
claims_user_id, claims_username, claims_email, claims_email_verified,
claims_groups,
claims_groups, claims_locale,
connector_id, connector_data,
token, created_at, last_used
from refresh_token;
Expand All @@ -362,7 +364,7 @@ func scanRefresh(s scanner) (r storage.RefreshToken, err error) {
err = s.Scan(
&r.ID, &r.ClientID, decoder(&r.Scopes), &r.Nonce,
&r.Claims.UserID, &r.Claims.Username, &r.Claims.Email, &r.Claims.EmailVerified,
decoder(&r.Claims.Groups),
decoder(&r.Claims.Groups), &r.Claims.Locale,
&r.ConnectorID, &r.ConnectorData,
&r.Token, &r.CreatedAt, &r.LastUsed,
)
Expand Down
12 changes: 12 additions & 0 deletions storage/sql/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,16 @@ var migrations = []migration{
);`,
},
},
{
stmts: []string{`
alter table auth_request
add column claims_locale text not null default '';`,
justin-slowik marked this conversation as resolved.
Show resolved Hide resolved
`
alter table auth_code
add column claims_locale text not null default '';`,
`
alter table refresh_token
add column claims_locale text not null default '';`,
},
},
}
4 changes: 2 additions & 2 deletions storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ type Claims struct {
Username string
Email string
EmailVerified bool

Groups []string
Groups []string
Locale string
}

// AuthRequest represents a OAuth2 client authorization request. It holds the state
Expand Down