You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Likely Bug in the GitHub OIDC Strategy preventing Private Email Addresses from being accessed
I've been trying to get the GitHub OAuth flow to work. Experimenting on my GitHub account where my email is private. Currently does not return the email address with scope set to user which supersedes user:email. Getting other information like claims.nickname, claims.name, claims.profile, claims.picture. But without the email, it's a fail.
I've done some digging and here's the code from the GitHub strategy where it clearly says:
GitHub does not provide the user's private emails in the call to /user. Therefore, if scope "user:email" is set, we want to make another request to /user/emails and merge that with our claims.
So reading the code below I see, it makes a ListEmails() call. Might want to check if this is actually working.
Check my Jsonnet below. I was able to retrieve the name from claims and parse it successfully for my Identity schema. That means, information is being retrieved. Just not the email. I've read the logs extensively using log.level set to trace
oidc.github.jsonnet:
local claims = std.extVar('claims');
{
identity: {
local name = std.split(claims.name, " "),
traits: {
// Allowing unverified email addresses enables account
// enumeration attacks, especially if the value is used for
// e.g. verification or as a password login identifier.
//
// Therefore we only return the email if it (a) exists and (b) is marked verified
// by GitHub.
// [if "email" in claims && claims.email_verified then "email" else null]: claims.email,
[if "email" in claims then "email" else null]: claims.email,
[if std.length(name) != 0 then "first_name" else null]: name[0],
[if std.length(name) != 0 then "last_name" else null]: name[1],
},
metadata_public: {
// Check if the issuer includes "github" and if preferred_username is available
local isGitHub = if std.findSubstr("github", claims.iss) != -1 then true else false,
github: {
[if isGitHub then "username"]: claims.nickname,
[if isGitHub then "profile"]: claims.profile,
[if isGitHub then "picture"]: claims.picture,
[if isGitHub && "email" in claims then "email" else null]: claims.email,
},
},
},
}
The config file looks like this:
selfservice:
# Browser requests, identified by the `Accept: text/html` header, complete with a redirection flow.# If no redirection URL is set for the flow, the Default Redirect URL will be used for most flows (for example login, registration)default_browser_return_url: "http://${BASE_URL}/"methods:
password:
enabled: trueprofile:
enabled: truelink:
enabled: trueoidc:
config:
providers:
- id: github # this is `<provider-id>` in the Authorization callback URL. DO NOT CHANGE IT ONCE SET!provider: githublabel: "GitHub"client_id: $(GH_CLIENT_ID) # Replace this with the Client IDclient_secret: $(GH_CLIENT_SECRET) # Replace this with the Client secretissuer_url: https://github.com # Replace this with the providers issuer URLauth_url: https://github.com/login/oauth/authorizetoken_url: https://github.com/login/oauth/access_tokenmapper_url: "file:///etc/kratos/oidc/oidc.github.jsonnet"scope:
- userenabled: true
Here's the thing with scopes for GitHub:
The user scope is not necessary. I have cross-verified by running this flow on Insomnia
https://api.github.com/user works without any scope and gives all details except private email addresses.
I can't see any reason why the email shouldn't be fetched, I just did it via Insomnia. Unless the ListEmails function, isn't working as expected or there's some problem with the code from there on.
// GitHub does not provide the user's private emails in the call to `/user`. Therefore, if scope "user:email" is set,// we want to make another request to `/user/emails` and merge that with our claims.ifstringslice.Has(grantedScopes, "user:email") {
emails, _, err:=gh.Users.ListEmails(ctx, nil)
iferr!=nil {
returnnil, errors.WithStack(herodot.ErrInternalServerError.WithReasonf("%s", err))
}
fork, e:=rangeemails {
// If it is the primary email or it's the last email (no primary email set?), set the email.ife.GetPrimary() ||k==len(emails) {
claims.Email=e.GetEmail()
claims.EmailVerified=x.ConvertibleBoolean(e.GetVerified())
break
}
}
}
Preflight checklist
Ory Network Project
No response
Describe the bug
Likely Bug in the GitHub OIDC Strategy preventing Private Email Addresses from being accessed
I've been trying to get the GitHub OAuth flow to work. Experimenting on my GitHub account where my email is private. Currently does not return the email address with scope set to
user
which supersedesuser:email
. Getting other information likeclaims.nickname
,claims.name
,claims.profile
,claims.picture
. But without theemail
, it's a fail.I've done some digging and here's the code from the GitHub strategy where it clearly says:
So reading the code below I see, it makes a
ListEmails()
call. Might want to check if this is actually working.Check my Jsonnet below. I was able to retrieve the
name
fromclaims
and parse it successfully for my Identity schema. That means, information is being retrieved. Just not the email. I've read the logs extensively usinglog.level
set totrace
oidc.github.jsonnet:
The config file looks like this:
Here's the thing with scopes for GitHub:
user
scope is not necessary. I have cross-verified by running this flow on Insomniahttps://api.github.com/user
works without any scope and gives all details except private email addresses.https://api.github.com/user/emails
: Requiresuser:email
. Lists email addresses.My Hunch
ListEmails
function, isn't working as expected or there's some problem with the code from there on.Something HERE
github.com/google/go-github/v38/github
package. It's quite an old version. This is the latest: github.com/google/go-github/v61/github.Some Log Files to help
0-oidc-login-middleware.json
1-redirect-to-github-422.json
2-422-middleware.json
3-received-redirect-cb.json
4-strategy-switch.json
5-registration-strategy.json
6-json-mapped-user.json
7-mapping-wrong.json
8-302-processed.json
09-redirect-to-signup.json
Reproducing the bug
Relevant log output
No response
Relevant configuration
No response
Version
v1.1.0
On which operating system are you observing this issue?
macOS
In which environment are you deploying?
Kubernetes
Additional Context
No response
The text was updated successfully, but these errors were encountered: