Skip to content
This repository has been archived by the owner on Dec 22, 2023. It is now read-only.

Redefine some OAuth claim keys #1435

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
11 changes: 9 additions & 2 deletions pkg/auth/dependency/identity/claim_key.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package identity

const (
// IdentityClaimOAuthProvider is a claim with a map value like `{ "type": "azureadv2", "tenant": "test" }`.
IdentityClaimOAuthProvider string = "https://auth.skygear.io/claims/oauth/provider"
// IdentityClaimOAuthProviderType is a claim with a string value.
// This claim is intended for external use only.
IdentityClaimOAuthProviderType string = "https://auth.skygear.io/claims/oauth/provider_type"
// IdentityClaimOAuthProviderAlias is a claim with a string value.
// This claim is intended for external use only.
IdentityClaimOAuthProviderAlias string = "https://auth.skygear.io/claims/oauth/provider_alias"
// IdentityClaimOAuthProviderKeys is a claim with a map value like `{ "type": "azureadv2", "tenant": "test" }`.
// This claim is intended for internal use only.
IdentityClaimOAuthProviderKeys string = "https://auth.skygear.io/claims/oauth/provider_keys"
// IdentityClaimOAuthSubjectID is a claim with a string value like `1098765432`.
IdentityClaimOAuthSubjectID string = "https://auth.skygear.io/claims/oauth/subject_id"
// IdentityClaimOAuthData is a claim with a map value containing raw OAuth provider profile.
Expand Down
22 changes: 21 additions & 1 deletion pkg/auth/dependency/identity/info.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package identity

import "github.com/skygeario/skygear-server/pkg/core/authn"
import (
"github.com/skygeario/skygear-server/pkg/auth/model"
"github.com/skygeario/skygear-server/pkg/core/authn"
)

type Info struct {
ID string `json:"id"`
Expand All @@ -16,3 +19,20 @@ func (i *Info) ToSpec() Spec {
func (i *Info) ToRef() Ref {
return Ref{ID: i.ID, Type: i.Type}
}

func (i *Info) ToModel() model.Identity {
claims := make(map[string]interface{})
for key, value := range i.Claims {
// Hide IdentityClaimOAuthProviderKeys because
// It may contain client_id, tenant or team_id.
if key == IdentityClaimOAuthProviderKeys {
continue
}
claims[key] = value
}

return model.Identity{
Type: string(i.Type),
Claims: claims,
}
}
27 changes: 1 addition & 26 deletions pkg/auth/dependency/identity/provider/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,31 +50,6 @@ func loginIDFromIdentityInfo(userID string, i *identity.Info) *loginid.Identity
return l
}

func oauthToIdentityInfo(o *oauth.Identity) *identity.Info {
provider := map[string]interface{}{
"type": o.ProviderID.Type,
}
for k, v := range o.ProviderID.Keys {
provider[k] = v
}

claims := map[string]interface{}{
identity.IdentityClaimOAuthProvider: provider,
identity.IdentityClaimOAuthSubjectID: o.ProviderSubjectID,
identity.IdentityClaimOAuthProfile: o.UserProfile,
}
for k, v := range o.Claims {
claims[k] = v
}

return &identity.Info{
Type: authn.IdentityTypeOAuth,
ID: o.ID,
Claims: claims,
Identity: o,
}
}

func oauthFromIdentityInfo(userID string, i *identity.Info) *oauth.Identity {
o := &oauth.Identity{
ID: i.ID,
Expand All @@ -83,7 +58,7 @@ func oauthFromIdentityInfo(userID string, i *identity.Info) *oauth.Identity {
}
for k, v := range i.Claims {
switch k {
case identity.IdentityClaimOAuthProvider:
case identity.IdentityClaimOAuthProviderKeys:
o.ProviderID.Keys = map[string]interface{}{}
for k, v := range v.(map[string]interface{}) {
if k == "type" {
Expand Down
56 changes: 47 additions & 9 deletions pkg/auth/dependency/identity/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (a *Provider) Get(userID string, typ authn.IdentityType, id string) (*ident
if err != nil {
return nil, err
}
return oauthToIdentityInfo(o), nil
return a.toIdentityInfo(o), nil

case authn.IdentityTypeAnonymous:
a, err := a.Anonymous.Get(userID, id)
Expand Down Expand Up @@ -114,7 +114,7 @@ func (a *Provider) GetByClaims(typ authn.IdentityType, claims map[string]interfa
if err != nil {
return "", nil, err
}
return o.UserID, oauthToIdentityInfo(o), nil
return o.UserID, a.toIdentityInfo(o), nil

case authn.IdentityTypeAnonymous:
keyID, _ := extractAnonymousClaims(claims)
Expand All @@ -141,7 +141,7 @@ func (a *Provider) GetByUserAndClaims(typ authn.IdentityType, userID string, cla
if err != nil {
return nil, err
}
return oauthToIdentityInfo(o), nil
return a.toIdentityInfo(o), nil
case authn.IdentityTypeAnonymous:
as, err := a.Anonymous.List(userID)
if err != nil {
Expand Down Expand Up @@ -180,7 +180,7 @@ func (a *Provider) ListByClaims(claims map[string]string) ([]*identity.Info, err
return nil, err
}
for _, i := range os {
all = append(all, oauthToIdentityInfo(i))
all = append(all, a.toIdentityInfo(i))
}

// Skip anonymous: no standard claims for anonymous identity
Expand All @@ -207,7 +207,7 @@ func (a *Provider) ListByUser(userID string) ([]*identity.Info, error) {
return nil, err
}
for _, i := range ois {
iis = append(iis, oauthToIdentityInfo(i))
iis = append(iis, a.toIdentityInfo(i))
}

// anonymous
Expand Down Expand Up @@ -241,7 +241,7 @@ func (a *Provider) New(userID string, typ authn.IdentityType, claims map[string]
}

o := a.OAuth.New(userID, providerID, subjectID, profile, oidcClaims)
return oauthToIdentityInfo(o)
return a.toIdentityInfo(o)

case authn.IdentityTypeAnonymous:
keyID, key := extractAnonymousClaims(claims)
Expand All @@ -268,7 +268,7 @@ func (a *Provider) WithClaims(userID string, ii *identity.Info, claims map[strin
}
i := oauthFromIdentityInfo(userID, ii)
i.UserProfile = profile
return oauthToIdentityInfo(i)
return a.toIdentityInfo(i)
case authn.IdentityTypeAnonymous:
panic("interaction_adaptors: update no support for identity type " + ii.Type)
}
Expand Down Expand Up @@ -495,6 +495,44 @@ func (a *Provider) ListCandidates(userID string) (out []identity.Candidate, err
return
}

func (a *Provider) toIdentityInfo(o *oauth.Identity) *identity.Info {
provider := map[string]interface{}{
"type": o.ProviderID.Type,
}
for k, v := range o.ProviderID.Keys {
provider[k] = v
}

claims := map[string]interface{}{
identity.IdentityClaimOAuthProviderKeys: provider,
identity.IdentityClaimOAuthProviderType: o.ProviderID.Type,
identity.IdentityClaimOAuthSubjectID: o.ProviderSubjectID,
identity.IdentityClaimOAuthProfile: o.UserProfile,
}

alias := ""
for _, providerConfig := range a.Identity.OAuth.Providers {
providerID := oauth.NewProviderID(providerConfig)
if providerID.Equal(&o.ProviderID) {
alias = providerConfig.ID
}
}
if alias != "" {
claims[identity.IdentityClaimOAuthProviderAlias] = alias
}

for k, v := range o.Claims {
claims[k] = v
}

return &identity.Info{
Type: authn.IdentityTypeOAuth,
ID: o.ID,
Claims: claims,
Identity: o,
}
}

func extractLoginIDClaims(claims map[string]interface{}) loginid.LoginID {
loginIDKey := ""
if v, ok := claims[identity.IdentityClaimLoginIDKey]; ok {
Expand Down Expand Up @@ -522,9 +560,9 @@ func extractOAuthClaims(claims map[string]interface{}) (providerID oauth.Provide
}

func extractOAuthProviderClaims(claims map[string]interface{}) oauth.ProviderID {
provider, ok := claims[identity.IdentityClaimOAuthProvider].(map[string]interface{})
provider, ok := claims[identity.IdentityClaimOAuthProviderKeys].(map[string]interface{})
if !ok {
panic(fmt.Sprintf("interaction_adaptors: expect map provider claim, got %T", claims[identity.IdentityClaimOAuthProvider]))
panic(fmt.Sprintf("interaction_adaptors: expect map provider claim, got %T", claims[identity.IdentityClaimOAuthProviderKeys]))
}

providerID := oauth.ProviderID{Keys: map[string]interface{}{}}
Expand Down
18 changes: 9 additions & 9 deletions pkg/auth/dependency/interaction/flows/auth_api_sso.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ func (f *AuthAPIFlow) LoginWithOAuthProvider(
) (string, error) {
providerID := oauth.NewProviderID(oauthAuthInfo.ProviderConfig)
claims := map[string]interface{}{
identity.IdentityClaimOAuthProvider: providerID.ClaimsValue(),
identity.IdentityClaimOAuthSubjectID: oauthAuthInfo.ProviderUserInfo.ID,
identity.IdentityClaimOAuthProfile: oauthAuthInfo.ProviderRawProfile,
identity.IdentityClaimOAuthClaims: oauthAuthInfo.ProviderUserInfo.ClaimsValue(),
identity.IdentityClaimOAuthProviderKeys: providerID.ClaimsValue(),
identity.IdentityClaimOAuthSubjectID: oauthAuthInfo.ProviderUserInfo.ID,
identity.IdentityClaimOAuthProfile: oauthAuthInfo.ProviderRawProfile,
identity.IdentityClaimOAuthClaims: oauthAuthInfo.ProviderUserInfo.ClaimsValue(),
}
i, err := f.Interactions.NewInteractionLogin(&interaction.IntentLogin{
Identity: identity.Spec{
Expand Down Expand Up @@ -93,10 +93,10 @@ func (f *AuthAPIFlow) LinkWithOAuthProvider(
) (string, error) {
providerID := oauth.NewProviderID(oauthAuthInfo.ProviderConfig)
claims := map[string]interface{}{
identity.IdentityClaimOAuthProvider: providerID.ClaimsValue(),
identity.IdentityClaimOAuthSubjectID: oauthAuthInfo.ProviderUserInfo.ID,
identity.IdentityClaimOAuthProfile: oauthAuthInfo.ProviderRawProfile,
identity.IdentityClaimOAuthClaims: oauthAuthInfo.ProviderUserInfo.ClaimsValue(),
identity.IdentityClaimOAuthProviderKeys: providerID.ClaimsValue(),
identity.IdentityClaimOAuthSubjectID: oauthAuthInfo.ProviderUserInfo.ID,
identity.IdentityClaimOAuthProfile: oauthAuthInfo.ProviderRawProfile,
identity.IdentityClaimOAuthClaims: oauthAuthInfo.ProviderUserInfo.ClaimsValue(),
}
i, err := f.Interactions.NewInteractionAddIdentity(&interaction.IntentAddIdentity{
Identity: identity.Spec{
Expand Down Expand Up @@ -185,7 +185,7 @@ func (f *AuthAPIFlow) UnlinkkWithOAuthProvider(
Identity: identity.Spec{
Type: authn.IdentityTypeOAuth,
Claims: map[string]interface{}{
identity.IdentityClaimOAuthProvider: providerID.ClaimsValue(),
identity.IdentityClaimOAuthProviderKeys: providerID.ClaimsValue(),
},
},
}, clientID, userID)
Expand Down
4 changes: 2 additions & 2 deletions pkg/auth/dependency/interaction/flows/user_ctrl.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func (c *UserController) CreateSession(

result.Response.SessionID = authSession.SessionID()

identity := model.NewIdentity(ir.Identity)
identity := ir.Identity.ToModel()
reason := auth.SessionCreateReasonLogin
if intent, ok := i.Intent.(*interaction.IntentLogin); ok {
if intent.OriginalIntentType == interaction.IntentTypeSignup {
Expand All @@ -108,7 +108,7 @@ func (c *UserController) CreateSession(
event.SessionCreateEvent{
Reason: string(reason),
User: result.Response.User,
Identity: *identity,
Identity: identity,
Session: *authSession.ToAPIModel(),
},
&result.Response.User,
Expand Down
26 changes: 13 additions & 13 deletions pkg/auth/dependency/interaction/flows/webapp_sso.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import (
func (f *WebAppFlow) LoginWithOAuthProvider(oauthAuthInfo sso.AuthInfo) (*WebAppResult, error) {
providerID := oauth.NewProviderID(oauthAuthInfo.ProviderConfig)
claims := map[string]interface{}{
identity.IdentityClaimOAuthProvider: providerID.ClaimsValue(),
identity.IdentityClaimOAuthSubjectID: oauthAuthInfo.ProviderUserInfo.ID,
identity.IdentityClaimOAuthProfile: oauthAuthInfo.ProviderRawProfile,
identity.IdentityClaimOAuthClaims: oauthAuthInfo.ProviderUserInfo.ClaimsValue(),
identity.IdentityClaimOAuthProviderKeys: providerID.ClaimsValue(),
identity.IdentityClaimOAuthSubjectID: oauthAuthInfo.ProviderUserInfo.ID,
identity.IdentityClaimOAuthProfile: oauthAuthInfo.ProviderRawProfile,
identity.IdentityClaimOAuthClaims: oauthAuthInfo.ProviderUserInfo.ClaimsValue(),
}
i, err := f.Interactions.NewInteractionLogin(&interaction.IntentLogin{
Identity: identity.Spec{
Expand Down Expand Up @@ -79,10 +79,10 @@ func (f *WebAppFlow) LoginWithOAuthProvider(oauthAuthInfo sso.AuthInfo) (*WebApp
func (f *WebAppFlow) LinkWithOAuthProvider(userID string, oauthAuthInfo sso.AuthInfo) (result *WebAppResult, err error) {
providerID := oauth.NewProviderID(oauthAuthInfo.ProviderConfig)
claims := map[string]interface{}{
identity.IdentityClaimOAuthProvider: providerID.ClaimsValue(),
identity.IdentityClaimOAuthSubjectID: oauthAuthInfo.ProviderUserInfo.ID,
identity.IdentityClaimOAuthProfile: oauthAuthInfo.ProviderRawProfile,
identity.IdentityClaimOAuthClaims: oauthAuthInfo.ProviderUserInfo.ClaimsValue(),
identity.IdentityClaimOAuthProviderKeys: providerID.ClaimsValue(),
identity.IdentityClaimOAuthSubjectID: oauthAuthInfo.ProviderUserInfo.ID,
identity.IdentityClaimOAuthProfile: oauthAuthInfo.ProviderRawProfile,
identity.IdentityClaimOAuthClaims: oauthAuthInfo.ProviderUserInfo.ClaimsValue(),
}

clientID := ""
Expand Down Expand Up @@ -126,7 +126,7 @@ func (f *WebAppFlow) UnlinkWithOAuthProvider(userID string, providerConfig confi
Identity: identity.Spec{
Type: authn.IdentityTypeOAuth,
Claims: map[string]interface{}{
identity.IdentityClaimOAuthProvider: providerID.ClaimsValue(),
identity.IdentityClaimOAuthProviderKeys: providerID.ClaimsValue(),
},
},
}, clientID, userID)
Expand Down Expand Up @@ -158,10 +158,10 @@ func (f *WebAppFlow) UnlinkWithOAuthProvider(userID string, providerConfig confi
func (f *WebAppFlow) PromoteWithOAuthProvider(userID string, oauthAuthInfo sso.AuthInfo) (*WebAppResult, error) {
providerID := oauth.NewProviderID(oauthAuthInfo.ProviderConfig)
claims := map[string]interface{}{
identity.IdentityClaimOAuthProvider: providerID.ClaimsValue(),
identity.IdentityClaimOAuthSubjectID: oauthAuthInfo.ProviderUserInfo.ID,
identity.IdentityClaimOAuthProfile: oauthAuthInfo.ProviderRawProfile,
identity.IdentityClaimOAuthClaims: oauthAuthInfo.ProviderUserInfo.ClaimsValue(),
identity.IdentityClaimOAuthProviderKeys: providerID.ClaimsValue(),
identity.IdentityClaimOAuthSubjectID: oauthAuthInfo.ProviderUserInfo.ID,
identity.IdentityClaimOAuthProfile: oauthAuthInfo.ProviderRawProfile,
identity.IdentityClaimOAuthClaims: oauthAuthInfo.ProviderUserInfo.ClaimsValue(),
}

clientID := ""
Expand Down
20 changes: 4 additions & 16 deletions pkg/auth/dependency/interaction/provider_commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,7 @@ func (p *Provider) onCommitAddIdentity(i *Interaction, intent *IntentAddIdentity
}

for _, i := range i.NewIdentities {
identity := model.Identity{
Type: string(i.Type),
Claims: i.Claims,
}
identity := i.ToModel()
err = p.Hooks.DispatchEvent(
event.IdentityCreateEvent{
User: *user,
Expand Down Expand Up @@ -203,10 +200,7 @@ func (p *Provider) onCommitRemoveIdentity(i *Interaction, intent *IntentRemoveId
}

for _, i := range i.RemoveIdentities {
identity := model.Identity{
Type: string(i.Type),
Claims: i.Claims,
}
identity := i.ToModel()
err = p.Hooks.DispatchEvent(
event.IdentityDeleteEvent{
User: *user,
Expand Down Expand Up @@ -287,14 +281,8 @@ func (p *Provider) onCommitUpdateIdentity(i *Interaction, intent *IntentUpdateId
if err != nil {
return err
}
originalIdentity := model.Identity{
Type: string(updateIdentityInfo.Type),
Claims: originalIdentityInfo.Claims,
}
updatedIdentity := model.Identity{
Type: string(updateIdentityInfo.Type),
Claims: updateIdentityInfo.Claims,
}
originalIdentity := originalIdentityInfo.ToModel()
updatedIdentity := updateIdentityInfo.ToModel()
err = p.Hooks.DispatchEvent(
event.IdentityUpdateEvent{
User: *user,
Expand Down
15 changes: 9 additions & 6 deletions pkg/auth/dependency/interaction/provider_commit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,19 @@ func TestProviderCommit(t *testing.T) {
}
userID := "userid1"
loginID1 := &identity.Info{
ID: "iid1",
Type: authn.IdentityTypeLoginID,
ID: "iid1",
Type: authn.IdentityTypeLoginID,
Claims: make(map[string]interface{}),
}
loginID2 := &identity.Info{
ID: "iid2",
Type: authn.IdentityTypeLoginID,
ID: "iid2",
Type: authn.IdentityTypeLoginID,
Claims: make(map[string]interface{}),
}
oauthID := &identity.Info{
ID: "iid3",
Type: authn.IdentityTypeOAuth,
ID: "iid3",
Type: authn.IdentityTypeOAuth,
Claims: make(map[string]interface{}),
}
pwAuthenticator := &authenticator.Info{
ID: "aid1",
Expand Down
Loading