I've integrated OAuth Implicit flow in Angular 8 App, I've been getting below issue initial time especially in Firefox (incognito).
Validating access_token failed, wrong state/nonce
Initial time, there is no nonce in the local storage, how can it validateNonce (angular-oauth2-oidc.js - 2358 line) execute? This method is being thrown an exception initial time.
if (this.configService.auth) {
console.log(this.configService.auth.authRedirectUri + "*&&&&&&&&&&&&&&&&&&dd");
this.authConfig = {
issuer: 'https://login.microsoftonline.com/XXXXXX/v2.0',
redirectUri: this.configService.auth.authRedirectUri,
clientId: this.configService.auth.clientId,
scope: 'openid profile email',
strictDiscoveryDocumentValidation: false,
oidc: true,
showDebugInformation: true,
// URL of the SPA to redirect the user after silent refresh
// silentRefreshRedirectUri: window.location.origin + '/login.html',
};
this.oauthService.configure(this.authConfig);
this.oauthService.setStorage(localStorage);
this.oauthService.tokenValidationHandler = new JwksValidationHandler();
this.oauthService.setupAutomaticSilentRefresh();
// this.oauthService.silentRefreshRedirectUri = window.location.origin + '/login.html';
}
// trylogin funtion
tryLogin(state?: any): Observable<boolean | any> {
console.log("***********Try Login", state);
return Observable.create(observer => {
return this.oauthService.loadDiscoveryDocument(this.configService.auth.openIdDocument).then(() => {
console.log("***********Try Login", state);
return this.oauthService.tryLogin({}).then(() => {
observer.next(state ? state : this.isLoggedIn);
observer.complete();
}).catch(err => {
observer.error(err);
observer.complete();
});
});
});
}
Desktop (please complete the following information):
more info to understand this issue,
This is happening very first time login with new browser in the Firefox. In this case, there is no nonce right so Nonce validation keep failing.
any update
Ermmm, it's been no more than 20 hours since you initially posted 😅 - there's not a large community here so it might take way longer to get an answer for questions. If you need faster feedback you could try Stack Overflow (they tend to have strict(er) rules about what you need to provide in a question for it to be answerable), or a colleague or paid consultant...
As a footnote, after glancing at your code, I can mention I had more success by providing configuration and storage options via the module, you could try if that helps fix your issue?
OP, did you ever try my suggestion? If not, could you help us figure out if you suspect a bug in the library, or have a question for help with your own implementation? For the latter I recommend Stack Overflow or a colleague/consultant though...
Can you please retry this with this libs version 9.1 when it ships later today?
TL;DR Ran into the same error with version 8.0.4 and it worked after upgrading to 9.2.0
My config:
private readonly config: AuthConfig = {
issuer: environment.loginServiceUrl,
redirectUri: window.location.origin + '/index.html',
clientId: '...',
requestAccessToken: true,
requireHttps: false,
disableAtHashCheck: true,
oidc: true,
scope: 'oidc account profile offline_access api',
showDebugInformation: true,
disablePKCE: true,
skipSubjectCheck: true,
};
and used this.auth.loadDiscoveryDocumentAndTryLogin()
With 8.0.4, I got the same error: Validating access_token failed, wrong state/nonce as there was no nonce in local storage. After upgrading, this works flawlessly.
I am using version 9.2.1 with IdentityServer 4 and have the same problem.
The first time you enter the site and log in, the error message mentioned above appears in the log.
Validating access_token failed, wrong state/nonce. null UnZFVkYtVkxqcHZibXphTEc5WEZOWTNhajRzd0Z5UDlXWU5sRENkWHRqQlM0
If I enter the url again I am immediately logged in without any problems.
To reproduce the problem I had to clear the browser cache.
My configuration looks like this:
{
issuer: environment.baseUrls.identityUrl,
redirectUri: environment.baseUrls.uiUrl,
postLogoutRedirectUri: environment.baseUrls.uiUrl,
clientId: 'spa',
scope: 'openid profile email services.api.read',
silentRefreshRedirectUri: environment.baseUrls.uiUrl + '/silent-refresh.html',
clearHashAfterLogin: false
}
and later using:
oauthService.loadDiscoveryDocumentAndLogin()
Is there any way to skip the nonce check?
I'm have the same issue when using this.oauthService.loadDiscoveryDocumentAndLogin()
Has this issue been fixed?
Exact same issue here (9.2.2).
"Validating access_token failed, wrong state/nonce."
The document is loaded, the login form is displayed and the redirect works (with the code and token in the URL) -> cannot finalize login process and get my token :(
I had the same issue using version 9.2.2 and Chrome or Firefox.
I stumbled upon https://github.com/manfredsteyer/angular-oauth2-oidc/issues/472#issuecomment-439694257 and it put me in the right direction. I was doing a loadDiscoveryDocumentAndLogin() in my AppComponent and also an initCodeFlow() in my AppGuard. Removing the call in the AppGuard solved the issue for me.
I am still wondering though why the issue did not appear on Safari.
The worst part of this is, the exception thrown causes an uncoverable application state in a way, that i am not able to redirect the user to any other page.
So my users see a never ending loading screen.
So again my question, is there any way to disable the nonce check or atleast let it not throw an error?
The ability to disable the nonce check might not be feasible, If I recall correctly it's mandatory by the spec?
Certainly there should be either:
However, I am thinking about closing _this_ specific issue. The original poster never responded anymore or tried Manfred's suggestion. Others commenting later about having the same _symptom_ might or might not experience the same _cause_, but we have no up to date reproducible scenario. So it might be better if someone opens a fresh issue with a reproducible scenario using the latest version of the library (or at the least post one in this issue), so we can trace the cause and fix that?
Again, by no means do I want to say that "there's no issue", I'm just looking for the clearest, most efficient path to getting a repro, and ultimately getting things resolved.
I also encountered the same error. i did not make any changes to this repository.
repro step:
yarn run startlogin button under login with code flowplease forgive me English is not very good
EDIT: I managed to get it to work using https://github.com/manfredsteyer/angular-oauth2-oidc/issues/728#issuecomment-590909947. This should still be fixed or documented somewhere that it is necessary.
The ability to disable the nonce check might not be feasible, If I recall correctly it's mandatory by the spec?
Certainly there should be either:
* no error (i.e. there might still be a bug in the library) * a _descriptive_ error explaining that something was misconfigured in the _app_, in a way that helps resolve the issueHowever, I am thinking about closing _this_ specific issue. The original poster never responded anymore or tried Manfred's suggestion. Others commenting later about having the same _symptom_ might or might not experience the same _cause_, but we have no up to date reproducible scenario. So it might be better if someone opens a fresh issue with a reproducible scenario using the latest version of the library (or at the least post one in this issue), so we can trace the cause and fix that?
Again, by no means do I want to say that "there's no issue", I'm just looking for the clearest, most efficient path to getting a repro, and ultimately getting things resolved.
Just created a fresh project using angular CLI and followed the minimal example and getting this error.
The local storage is empty (no state stored). So this is definitely a bug.
Currently I am testing on localhost.
The nonce is not mandatory in OIDC and definitely not in RFC 6749. Not sure about the current security BCP draft right now.
Anyway. Still a bug no matter how the plugin handles and interprets the state parameter. But basically it currently enforces the use of a nonce which is piggybacked in the state leading to the error due to the bug.
Hi @jeroenheijmans , I had partial success with the below code
this.oauthService.events
.pipe(filter((e: any) => e.type === 'invalid_nonce_in_state'))
.subscribe(() => {
console.log('invalid_nonce_in_state');
this.oauthService.initImplicitFlow();
});
I have implemented the library in APP_INITIALIZER and using version 10.0.3.
I tried reproducing the issue with This comment
Your view on this? although this solution does not work when multiple tabs cause this same issue at a time.
I had the same issue and it turned out that for us using localStorage was the problem.
In my module i had:
providers: [
...
{
provide: OAuthStorage,
useValue: localStorage
}
]
The library then seems to mix session and localStorage resulting in the nonce being retrived from the "wrong" one.
Seems like a bug to me, if the provider is set to local, all storage should be set/retrieved from local.
We swiched to sessionStorage (the default) and it works fine now. (version 9.0.1)
The issue can be reproduced with the sample app:
angular-oauth2-oidc\projects\sample with npm start-> After the redirect back to the sample app the main content of the app is empty.
-> Following can be found in the console:
Validating access_token failed, wrong state/nonce. null V2Q4NmdvUU13WWVOMzc0RHpWMWRrRTVLSG9sRTlNaG1EZkt3a2RZdF9zRFhf
.../lib/src/oauth-service.ts.OAuthService.validateNonce | @ | oauth-service.ts:1966
.../lib/src/oauth-service.ts.OAuthService.tryLoginCodeFlow | @ | oauth-service.ts:1656
.../lib/src/oauth-service.ts.OAuthService.tryLogin | @ | oauth-service.ts:1599
[...]
ERROR Error: Uncaught (in promise): OAuthErrorEvent: {"type":"invalid_nonce_in_state","reason":null,"params":null}
at resolvePromise (zone.js:832)
at resolvePromise (zone.js:784)
at zone.js:894
at ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:27164)
at ZoneDelegate.invokeTask (zone.js:420)
at Zone.runTask (zone.js:188)
at drainMicroTaskQueue (zone.js:601)
at ZoneTask.invokeTask [as invoke] (zone.js:507)
at invokeTask (zone.js:1671)
Maybe the problem occurs if you do not use the default storage and you use the authorization already in the APP_INITIALIZER because the storageFactory for OAuthStorage is not yet initialized and the default is used instead of the configured one.
I can only reproduce on Firefox, Chrome is fine.
I wrote a workaround that stores the nonce and pkce verifier in localstorage. I would like to understand what's going on and why only firefox. I suspect maybe firefox handels localhost differently. Anyhow I implemented the OAuthStorage class like this and provided it in my core module.
export class LocalNonceStorage implements OAuthStorage {
private needsLocal(key: string) {
return key === 'nonce' || key === 'PKCE_verifier';
}
getItem(key: string) {
if (this.needsLocal(key)) {
return localStorage.getItem(key);
}
return sessionStorage.getItem(key);
}
removeItem(key: string) {
if (this.needsLocal(key)) {
return localStorage.removeItem(key);
}
return sessionStorage.removeItem(key);
}
setItem(key: string, data: string) {
if (this.needsLocal(key)) {
return localStorage.setItem(key, data);
}
return sessionStorage.setItem(key, data);
}
}
export function storageFactory(localNonceStorage: LocalNonceStorage): OAuthStorage {
return localNonceStorage;
}
export class CoreModule {
static forRoot(): ModuleWithProviders<CoreModule> {
return {
ngModule: CoreModule,
providers: [
{ provide: LocalNonceStorage, useClass: LocalNonceStorage },
{ provide: AuthConfig, useValue: authConfig },
{ provide: OAuthModuleConfig, useValue: authModuleConfig },
{ provide: OAuthStorage, useFactory: storageFactory, deps: [LocalNonceStorage] }]
};
}
constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
if (parentModule) {
throw new Error('CoreModule is already loaded. Import it in the AppModule only');
}
}
}
I am able to reproduce this issue with the below code
Custom storage
import { OAuthStorage } from 'angular-oauth2-oidc';
export class MemoryStorageService implements OAuthStorage {
private data = new Map<any, any>();
getItem(key: string): string {
return this.data.get(key);
}
removeItem(key: string): void {
this.data.delete(key);
}
setItem(key: string, data: string): void {
this.data.set(key, data);
}
}
Login Module
export function createDefaultStorage() {
return new MemoryStorageService();
}
@NgModule({
imports: [
CommonModule,
HttpClientModule,
OAuthModule.forRoot({
resourceServer: {
allowedUrls: [], //http://www.angular.at/api allowed url we can add it here.
sendAccessToken: true
}
})
],
providers: [
{ provide: OAuthStorage, useFactory: createDefaultStorage }
]
})
export class loginModule {}
⚠️ This comment is a _specific_ reply, about the code in previous post. Not a general remark about the library.
@manandkumaar Well that makes sense. Both Implicit and Code flow include a redirect. After the redirect your Storage implementation will have 'lost' the nonce that was set.
Think of it this way:
nonce in OAuthStorage before sending you to the IDS domainnonce in the URL)MemoryStorage but won't reload the nonce it knew in step 1nonce in the URL as passed along by IDS (this is a security check) and tries to compare it to whatever the Angular app saved in step 1In short, you can _not_ use a full MemoryStorage solution for OAuthStorage. You need to use either sessionStorage, localStorage, or a custom implementation that persists data across redirects (for example cookies or indexdb). Or as an ultimate workaround you could sniff out the key and persist specifcally nonce in more persistent storage.
Hope that helps!
So is the issue that the library is not using local or session storage by default? Considering that authorization code flow is the only flow to be used for OIDC according the current OAuth2 BCP this should either be documented properly or the default changed. The only use case a memory store would make sense is ROPC which is not recommended.
Or is is a browser implementation issue?
Im my opinion, an no matter the cause, the library should just behave by default as if the sessionstorage is configured explicitly.
So is the issue that the library is not using local or session storage by default?
Careful, my comment was a reply _very specific_ to another user. In their snippet they override the default.
The default from the library _is_ sessionStorage.
I think the issue is that Firefox somehow clears the state from sessionstorage before navigating to the identity provider
On 24 Mar 2021, at 13:23, Jeroen Heijmans @.*> wrote:
So is the issue that the library is not using local or session storage by default?Careful, my comment was a reply very specific to another user. In their snippet the override the default.
The default from the library is sessionStorage.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
There's many different people in this thread commenting, probably experiencing the same _symptoms_ and _possibly_ the same root cause.
⁉ What we really need is a reliable (and preferably minimal) way to reproduce this.
For example:
Without a reproducible scenario, we can't find the root cause, or verify if people have the same or separate issues. I'm happy to help investigate, but all we have to go on currently are various partial code snippets, too many blanks to fill in.
Hi @jeroenheijmans - some time ago I posted how I could reproduce the issue with the sample app: https://github.com/manfredsteyer/angular-oauth2-oidc/issues/728#issuecomment-722987671
Thx @synth3, I've traced the problem in the sample application and will add a PR to fix it there.
This also strengthens my suspicion as to what other people in this thread are experiencing.
Most likely you have the same problem as the sample application has. If you configure setStorage(...) at incorrect times, a nonce might get stored in a _different_ storage than is used when validating when you get back to your app.
The easy way to validate if this is happening to you, is if you get an error similar to:
Validating access_token failed, wrong state/nonce. null V2Q4NmdvUU13WWVOMzc0RHpWMWRrRTVLSG9sRTlNaG1EZkt3a2RZdF9zRFhf
Check _both_ localStorage _and_ sessionStorage. Most likely the library is finding null in one storage, when the nonce is actually saved in the other type of storage.
Solution in this case: make sure you setStorage before tryLogin. Or consider using Angular's DI and provide: OAuthStorage.
Another (dirty!) way to check if you have this problem is by doing (this.oauthService as any).saveNoncesInLocalStorage = true; as early as possible. Do _not_ rely on this as a _solution_ though, as you're abusing a protected feature that's intended to handle an MSIE bug.
Also, I personally prefer a different approach, which you can try in your app to solve the issue. It relies on using Angular DI to provide storage and config, and a very specific login sequence.
If you still believe you have the same _symptom_ but a different root cause: please open a fresh issue, but do include precise steps to reproduce the issue. That way we can trace any further bugs. Thanks!!
I'm having the same problem with the Firefox browser and Code Flow.
In my case I'm setting localstorage by storageFactory using Angular DI.
@mliotinoca That's unfortunate! But plz create a (preferably minimal) way for us to reproduce the issue, otherwise there's no way to tell if it's a bug or not.
@mliotinoca That's unfortunate! But plz create a (preferably minimal) way for us to reproduce the issue, otherwise there's no way to tell if it's a bug or not.
@jeroenheijmans I'm sorry but at the moment I have no way; I can only add that the issue also occurs on Safari on iPad.
No worries, but then we can't do much more here of course. (Except merging my PR to solve the version of this bug that _is_ reproducible.)
Thanks for all the efforts. Can the fix be merged and released?
Most helpful comment
Thanks for all the efforts. Can the fix be merged and released?