-
Notifications
You must be signed in to change notification settings - Fork 368
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
[SDK-2692] Remember organization ID for silent authentication #788
Conversation
src/Auth0Client.ts
Outdated
this.orgHintCookieName, | ||
decodedToken.claims.org_id | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to remove the cookie if there is no org_id
available?
else {
this.cookieStorage.remove(this.orgHintCookieName);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there's no org_id
claim it means that the user did not sign in in the context of an organization, so IMO it makes sense to remove the cookie so that we don't try to use it the next time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I was asking because in the above case, we are not removing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, I've added this now in 98dda60
src/Auth0Client.ts
Outdated
this.cookieStorage.remove( | ||
buildOrganizationHintCookieName(this.options.client_id) | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we not setting the cookie here? I assume it is because we know it is already set at this point? But it's not entirely clear for me if this is actually 100% guaranteed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason we are not using this.orgHintCookieName
here instead of buildOrganizationHintCookieName(this.options.client_id)
?
However, curious to know if it would make sense to drop this.orgHintCookieName
and use buildOrganizationHintCookieName(this.options.client_id)
everywhere. It would allow to work if client_id
is ever changed after constructing an Auth0Client (Not sure we should explicitly support that, but we could).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we not setting the cookie here?
We could set it here as well, I think that's fine.
Any reason we are not using this.orgHintCookieName here
I think that's just an oversight, I'd like to use it here as well. I did start down the road of just calling the function but I think if we wanted to support changing the client ID (can't think of a use-case right now) there'd be more work to do than just this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will also need to review getTokenWithPopup
as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 0211ca7. getTokenWithPopup
looks to be ok as it just calls loginWithPopup
anyway.
Converting back to a draft for the meantime. I've identified a couple E2E tests I want to put in, as well as fix the existing broken one. For the broken one, I'm still trying to figure out why its needed. The name of the test is "retrieves an access token for another audience using a refresh token" which is not something you can actually do. What it's actually testing is that the fallback to an iframe works but there's nothing about the test that should cause that to happen. Looking into it today. |
I'm ready for a review now. I had intentions to get an E2E test set up for this but it specifically means intercepting the call to |
…ct, and show options
6b9660f
to
5ae2326
Compare
Cypress.Commands.add('toggleSwitch', name => | ||
cy.get(`[data-cy=switch-${name}]`).click() | ||
); | ||
Cypress.Commands.add('setSwitch', (name, value) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I refactored toggleSwitch
into setSwitch
where you explicitly set the value of the switch so you can see exactly what it's set to in a test. toggleSwitch
requires you to understand what the default for that switch is, which is poor.
claims: { | ||
org_id: null | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't see a better way to do this, but this config for node-oidc-provider
allows it to return an org_id
claim, by specifying the claims
parameter to the authentication request. Ideally, I'd like the server to just echo back the organization
value in the org_id
claim but couldn't find a good way to do it or if that scenario is supported by the server. Makes sense if it's strictly OIDC compliant.
https://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter
<input | ||
type="checkbox" | ||
class="form-check-input" | ||
id="org-login-check" | ||
v-model="useOrgAtLogin" | ||
data-cy="useOrgAtLogin" | ||
/> | ||
<label for="org-login-check" class="form-check-label" | ||
>Apply only at loginWithRedirect</label | ||
> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This allows us to toggle whether the organization ID is given to the constructor options, or only to loginWithRedirect
for easy testing.
<div class="col-md-12"> | ||
<h3 class="mb-3">Client Options</h3> | ||
|
||
<pre><code>{{ clientOptions }}</code></pre> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Writing these options out just makes it easier to debug.
if (_self.organization) { | ||
const claims = { | ||
id_token: { | ||
org_id: { values: [_self.organization] } | ||
} | ||
}; | ||
|
||
clientOptions.claims = JSON.stringify(claims); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is setting the claims
parameter for the authentication call. Used when using node-oidc-provider
as the OP, ignored by Auth0 completely (looks like it doesn't support it).
Key changes:
org_id
claim is returned in the ID token, the SDK stores it in a new cookie to act as a "hint" for silent authenticationgetTokenSilently
with iframe +prompt=none
, if the hint cookie is available and no value fororganization
was given in the options, the value from the cookie is read and sent to the authorization requestorganization
is present in the options, the options value takes precedenceorg_id
claim in the ID tokenI also evolved the playground a bit so that you can toggle the organization ID being passed through constructor options or directly to
loginWithRedirect
. I also added JSON output at the bottom so that the options being used to initialize the SDK are visible.