openid / AppAuth-JS

JavaScript client SDK for communicating with OAuth 2.0 and OpenID Connect providers.
Apache License 2.0
977 stars 162 forks source link

code_verifier can be written in 'local storage' in localhost but can not in a hosted domain #121

Closed jonathan-fan-versent closed 5 years ago

jonathan-fan-versent commented 5 years ago

Expected Behavior

[REQUIRED] Describe expected behavior

During 'performAuthorizationRequest', internal.code_verifier should be written into local storage for both localhost and hosted domain. Need to retrieve code_verifier from local storage to get tokens. Or if there is a better way to get internal.code_verifier, please let me know. Thanks a lot.

Describe the problem

[REQUIRED] Actual Behavior

When deployed code to a hosted domain, the whole internal property is missing in Chrome and IE 11. Please refer to the following screenshot, the left-hand side is hosted domain which doesn't have internal.code_verifier, and the right-hand side is localhost which has internal.code_verifier

Vff_Mock_UI_and_Vff_Mock_UI

[REQUIRED] Steps to reproduce the behavior

[REQUIRED] Environment

export async function authenticate() { const config = await getConfig();

const request = new AuthorizationRequest({ client_id: CLIENT_ID, redirect_uri: redirectUri, scope: 'offline_access', response_type: AuthorizationRequest.RESPONSE_TYPE_CODE }); const authorizationHandler = new RedirectRequestHandler(); authorizationHandler.performAuthorizationRequest(config, request); } // ... export async function getTokensByCode({ code }) { const config = await getConfig(); const currentAuthRequestValue = localStorage.getItem('appauth_current_authorization_request'); const { internal: { code_verifier}} = JSON.parse(localStorage.getItem(currentAuthRequestValue + '_appauth_authorization_request')); const request = new TokenRequest({ client_id: CLIENT_ID, redirect_uri: redirectUri, grant_type: GRANT_TYPE_AUTHORIZATION_CODE, code, extras: { code_verifier } }); const tokenHandler = new BaseTokenRequestHandler(requestor); return await tokenHandler.performTokenRequest(config, request); }

tikurahul commented 5 years ago

You cannot write to local storage on behalf of another domain. Also, if you want to, you can shim LocalStorageBackend and implement it to do whatever you want.

I am also unsure about exactly what the problem seems to be ? Why do you want the verifier on both domains ?

jonathan-fan-versent commented 5 years ago

Hi @tikurahul, thanks for your reply.

I am not trying to write to local storage on behalf of another domain. After deploying to prod env I need internal.code_verifier to be written in local storage under prod domain.

The problem is:

The left-hand side screenshot is taken on prod domain, which doesn't have internal.code_verifier.

As you can see from the code, the TokenRequest needs code_verifier to pass in.

tikurahul commented 5 years ago

Why can't you write it in the prod domain though ?

If you are relying on localstorage it should work (unless the user is in incognito mode).

jonathan-fan-versent commented 5 years ago

The user is not in incognito mode, and I don't have control of writing it. I am using RedirectRequestHandler, and here is the code from AppAuth. https://github.com/openid/AppAuth-JS/blob/master/src/redirect_based_handler.ts#L63-L71

tikurahul commented 5 years ago

You have full control on the LocalStorageBackend. Also what is the error you are seeing ? I am still unclear why everything but the verifier is getting saved ?

jonathan-fan-versent commented 5 years ago

That's the same question I am asking here: 'why everything but the internal is getting saved'.

The error message is 'code_verifier' is undefined as I am trying to get it from local storage which should have internal.code_verifier.

and even I have full control of LocalStorageBackend, the code_verifier and challenge are generated within https://github.com/openid/AppAuth-JS/blob/master/src/authorization_request.ts#L79-L101 and doesn't expose to the outside app.

tikurahul commented 5 years ago

I have no idea why. This is your code and your deployment. It works well in the sample app and from what I can tell in your local environment. You have to debug and figure things out.

You have access to the internal data via the internal property. You are creating the request to begin with. This is a low level OAuth2 API and you have to understand what's going on.

If you have a better bug report, please feel free to reopen the bug. Otherwise Stackoverflow might be a better place to ask.

fungiboletus commented 5 years ago

Hei all, I have the same problem and perhaps some clues to identify the cause :

I don't know if you want to reopen this issue, but I feel like this is a better place than Stackoverflow to discuss about this weird behaviour.

My guess is that Chromium browsers don't like localStorage and sessionStorage anymore on non HTTPS or localhost.

BR0kEN- commented 4 years ago

To make it work in IE11 you'll need almost everything from the list:

import 'core-js/features/promise';
import 'core-js/features/object';
import 'core-js/features/array';
import 'core-js/features/array-buffer';
import 'core-js/web';
import 'whatwg-fetch';
import 'webcrypto-shim';

The problem with code_verifier in particular caused by the missing window.crypto and even having window.crypto = window.crypto || window.msCrypto is not a cure because msCrypto does not return promises but CryptoOperation.

https://developer.mozilla.org/ru/docs/Web/API/SubtleCrypto/digest