Skip to content

Commit

Permalink
feat: Use id from https://graph.microsoft.com/v1.0/me as oidc subject.
Browse files Browse the repository at this point in the history
  • Loading branch information
splaunov committed Feb 1, 2022
1 parent d9c8217 commit 78de615
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 1 deletion.
13 changes: 13 additions & 0 deletions embedx/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,19 @@
"contoso.onmicrosoft.com"
]
},
"subject_source": {
"title": "Microsoft subject source",
"description": "Controls from which endpoint the subject identifier is taken by microsoft provider",
"type": "string",
"enum": [
"userinfo",
"me"
],
"default": "userinfo",
"examples": [
"userinfo"
]
},
"team_id": {
"title": "Apple Developer Team ID",
"description": "Apple Developer Team ID needed for generating a JWT token for client secret",
Expand Down
7 changes: 7 additions & 0 deletions selfservice/strategy/oidc/provider_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ type Configuration struct {
// `8eaef023-2b34-4da1-9baa-8bc8c9d6a490` or `contoso.onmicrosoft.com`.
Tenant string `json:"tenant"`

// SubjectSource is a flag which controls from which endpoint the subject identifier is taken by microsoft provider.
// Can be either `userinfo` or `me`.
// If the value is `uerinfo` then the subject identifier is taken from sub field of uderifo standard endpoint response.
// If the value is `me` then the `id` field of https://graph.microsoft.com/v1.0/me response is taken as subject.
// The default is `userinfo`.
SubjectSource string `json:"subject_source"`

// TeamId is the Apple Developer Team ID that's needed for the `apple` `provider` to work.
// It can be found Apple Developer website and combined with `private_key` and `private_key_id`
// is used to generate `client_secret`
Expand Down
46 changes: 45 additions & 1 deletion selfservice/strategy/oidc/provider_microsoft.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package oidc

import (
"context"
"encoding/json"
"net/http"
"net/url"
"strings"

Expand Down Expand Up @@ -67,7 +69,49 @@ func (m *ProviderMicrosoft) Claims(ctx context.Context, exchange *oauth2.Token)
return nil, errors.WithStack(herodot.ErrInternalServerError.WithReasonf("Unable to initialize OpenID Connect Provider: %s", err))
}

return m.verifyAndDecodeClaimsWithProvider(ctx, p, raw)
claims, err := m.verifyAndDecodeClaimsWithProvider(ctx, p, raw)
if err != nil {
return nil, err
}

return m.updateSubject(ctx, claims, exchange)
}

func (m *ProviderMicrosoft) updateSubject(ctx context.Context, claims *Claims, exchange *oauth2.Token) (*Claims, error) {
if m.config.SubjectSource == "me" {
o, err := m.OAuth2(ctx)
if err != nil {
return nil, errors.WithStack(herodot.ErrInternalServerError.WithReasonf("%s", err))
}

client := o.Client(ctx, exchange)

u, err := url.Parse("https://graph.microsoft.com/v1.0/me")
if err != nil {
return nil, errors.WithStack(herodot.ErrInternalServerError.WithReasonf("%s", err))
}
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
return nil, errors.WithStack(herodot.ErrInternalServerError.WithReasonf("%s", err))
}

resp, err := client.Do(req)
if err != nil {
return nil, errors.WithStack(herodot.ErrInternalServerError.WithReasonf("%s", err))
}
defer resp.Body.Close()

var user struct {
Id string `json:"id"`
}
if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
return nil, errors.WithStack(herodot.ErrInternalServerError.WithReasonf("%s", err))
}

claims.Subject = user.Id
}

return claims, nil
}

type microsoftUnverifiedClaims struct {
Expand Down

0 comments on commit 78de615

Please sign in to comment.