soofstad / react-oauth2-pkce Goto Github PK
View Code? Open in Web Editor NEWProvider agnostic OAuth2 Authorization Code flow with PKCE for React
License: MIT License
Provider agnostic OAuth2 Authorization Code flow with PKCE for React
License: MIT License
Amazon Cognito allows for two custom parameters at the time of sending the request to the authorization endpoint to specify the identity provider that will be used. These parameters are identity_provider
and idp_identifier
as described in their documentation https://docs.aws.amazon.com/cognito/latest/developerguide/authorization-endpoint.html.
As of now the package allows for extraAuthParams
at the time of getting the tokens but not at the time of getting the login url when using the /authorize endpoint.
Is there any reason this is not supported or is it possible to enable extraAuthorizationParams
that can be passed to the /authorize
endpoint?
Setup component as below:
const authConfig: TAuthConfig = {
autoLogin: false,
...
};
function AuthenticationWrapper({ children }) {
return <AuthProvider authConfig={authConfig}>{children}</AuthProvider>;
}
Load app.
Console error:
console.error
Bad authorization state. Refreshing the page might solve the issue.
at node_modules/react-oauth2-code-pkce/dist/AuthContext.js:133:25
Should not produce error until we are expecting to be logged in. Or perhaps it should just be a warning.
Hi there, can you please expose this function as well, so that it can support the tokens retrieved via a middleware instead of getting token from Keycloak server directly.
react-oauth2-pkce/src/AuthContext.tsx
Line 92 in 3185e79
2 things.
1.Document mentions that redirect uri is supposed to be the location where auth should take user after user logs out. But after we log in, we are redirected to the "redirectUri"
2. I logout user using the logOut() function while having the logoutRedirect to some other path, but it still takes me to the "redirectUri"
3. Note: my xyz.com/logout which is my logout endpoint, it is not completely operational, but What I expect at the moment is that after clicking out, I should be redirected to xyz.com/logout.
Any thoughts about this
Here is my authconfig
const authConfig: TAuthConfig = {
clientId: process.env.REACT_APP_CLIENT_ID || '',
authorizationEndpoint:
process.env.REACT_APP_OAUTH_AUTHORIZATION_ENDPOINT || '',
tokenEndpoint: process.env.REACT_APP_TOKEN_ENDPOINT || '',
redirectUri: 'http://localhost:3000/oauth/callback',
scope: process.env.REACT_APP_SCOPE,
autoLogin:false,
postLogin: () => {
window.location.replace('http://localhost:3000');
},
logoutEndpoint:'https://xyz.com/logout',
logoutRedirect:'https://xyz.com/logout'
};
Cheers
Thanks.
Accepting any as function parameter can lead to unsafe member access, misused promises, unsafe assignment, its a source to many bugs.. It accepts class declarations etc. which will throw at runtime as they will not be called with new.
location
is considered a confusing browser global and should use the window
prefix
I'm using ping federate as provider, when ever making a request with grant type as refresh token getting 401, reason Ping Federate is expecting client secret which I have configured as extra params, is it possible to pass the extra parameters in the refresh token request, like original request ?
Failed refresh requests are not always identified to be caused by an expired refresh_token.
The way this is handled today is too brittle, and requires manually maintaining a list of known error responses from all possible authentication servers.
Suggestion:
Make a broader assumption like if the refresh request fails with a "400" (40x?) status code, that it's caused by an expired refresh_token.
Currently doesn't "log out", only clears client side info but doesn't redirect to logout endpoint.
Should log out on server and client.
With Strict Mode starting in React 18, whenever a component mounts in development, React will simulate immediately unmounting and remounting the component.
As a result, the same auth code will be sent to the auth provider twice, and the second time will get an error.
As React document mentions, it requires components to be resilient to effects being mounted and destroyed multiple times.
root.render( <React.StrictMode> <AuthProvider authConfig={authConfig}> <LoginInfo /> </AuthProvider> </React.StrictMode> );
The useEffect() in AuthProvider is fired twice, and the same auth code is sent to the auth provider twice.
The same auth code should not be sent to the auth provider twice.
Btw, I am not a front-end developer, so maybe my understanding of the error is not correct.
Ability to override access token expire actions
1.Login
2. Wait for token to expire
3. It logins automatically
It logins automatically
It logins automatically, but would be nice to have the possibility to override this behavior and logout, for example.
You should attribute your use of code from SO:
https://stackoverflow.com/a/69058154/1144060
72e7f03#diff-a4d7dc8b515316a4b9b1e9a73f77e9e170553e72b4c33a23c1027f3bee0608a2R98
Since v1.13.4 we've an issue that the auto login is triggered after returned and login is in progress. This causes an infinity loop authorizing and the fetchTokens call cancelled.
Application loops infinity to authorize endpoint (autoLogin login()) and trying to fetch token
No concurrent token fetch and auto login trigger
POST Requests for a token and refresh token MUST be in 'application/x-www-form-urlencoded' format according to the OAuth 2.0 spec. https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3.
Currently the code uses multi-part POST requests which is rejected by some Identity Providers.
The library should not automatically trigger a new login when the refresh token expires. This could cause the user to lose state.
Instead, we provide a call back that can be used to display a "Session expired" message. The user can then chose to login again.
Is there a reason why the latest release of react-oauth-pkce
(1.4.0) has React dependencies (react
and @types/react
) that are versioned to not include v18?
logged in first time with ouath2 verification & shut the browser and second time takes me straight through.
no localstorage cleanup option on configuration.
open browser, open page, user was already logged
open browser, open page, ouath2 login must be started
Hello,
First of all, thanks for the library, saved me a lot of implementation time.
I have a question about refresh tokens.
In the features it said "Silently refreshes short-lived access tokens in the background", now, I know the callback "onRefreshTokenExpire" but on that one the only event that can be given is the login (which causes the app to go back and forth through the processes which results in page refresh).
Am I missing something that can be configured to actually silently refresh tokens (so the user does not get a page refresh) or I need to implement a custom function myself to obtain that?
Thanks in advance.
Frameworks that relies on any kind of server-side-rendering does not have window.local-/sessionStorage
available.
Since these functions are called when loading the <AuthProvider> in this library, a compile error will be raised; localStorage is not defined
.
The most basic usage in Next.js will produce this
export default function App({ Component, pageProps }: AppPropsWithLayout) {
return (
<AuthProvider authConfig={authConfig(router)}>
<Layout>
</AuthProvider>
)
);
}
Known workaround is to only render the component after a useEffect
has run. The library will then never run on server.
export default function App({ Component, pageProps }: AppPropsWithLayout) {
const [isClient, setIsClient] = useState(false);
useEffect(() => setIsClient(true), []);
return (
isClient && (
<AuthProvider authConfig={authConfig(router)}>
<Layout>
</AuthProvider>
)
);
}
Depends on the implementation, possibly more complexity.
No response
No response
Hi there, can you please fix this issue, it should use logout redirect Url instead of redirect URL.
react-oauth2-pkce/src/authentication.ts
Line 110 in 52d639e
If base url of my application is http://localhost:3000/login and I try to start the authorisation process, it doesn't hit token endpoint and then i am stuck on login screen.
It works fine if my login page is at http://localhost:3000/
Sharing screenshot for the number calls happening at http://localhost:3000/login
Any reason scope cannot be removed from request? If undefined in config, it defaults to empty string.
react-oauth2-pkce/src/authConfig.ts
Line 14 in 8acce0f
For some cases, automatically logging in on page load might not be suitable.
There should be a option to set loginOnPageLoad: false
.
The login()
function also needs to be exported by the <AuthContext> so manual login is possible.
With the new JSX transform in React v17, there's no longer needed to import React to use jsx elements.
I use AWS Cognito as the auth provider. As required by Cognito, the below screenshot shows the logout GET request format.
In the code, it sends token, token_type_hint, client_id and post_logout_redirect_uri as the parameters, which does not match the Cognito format.
Can logout from my app. When log out from Cognito, shows error: Required String parameter 'redirect_uri' is not present.
Can logout from my app and Cognito.
Hey guys.
I'm not considering it as a bug, because it works fine for some providers. But, sometimes we need pass a credential cookie for custom providers, and by default, the fetch method not sends cookies on HTTP requests.
To resolve it, I just created a request interceptor for the fetch method, adding the property "credentials": "include" in the options object. I'm not sure if it can be added as a parameter on the context configurations, like "allowCookies" or something like that, to be flexible for the dev choose use it or no.
That's the created interceptor:
window.fetch = (...args): any => {
let [resource, options] = args;
if (options) {
options["credentials"] = "include";
options["mode"] = "cors";
}
return originalFetch(resource, options);
};
Changing the property, you need explicitly the CORS configuration, like the code below.
No response
No response
No response
Per idToken spec, the client should send a state
with the code request, and check that this is the same before using the code to redeem a token.
I'm having issues with redirecting my app to the auth providers logout page. In short, my auth provider do not issue any refresh tokens (this is apparently the case in a Client Credentials Grant scheme). Hence, I'm blocked from redirecting by this line:
react-oauth2-pkce/src/AuthContext.tsx
Line 99 in 9496763
Thoughts?
It would be nice to users of the package, if there where some checks on the availability of some of the functions that could be unavailable.
This check could print some more verbose error message that would help in debugging.
Instead of getting;
TypeError: Cannot read properties of undefined (reading 'digest')
when calling window.crypto.subtle.digest('SHA-256', bytes)
.
We could print Error: The context/environment is not secure, and does not support the 'crypto.subtle' module. See: https://developer.mozilla.org/en-US/docs/Web/API/Crypto/subtle for details
I believe there could be more examples like this:
None
No response
No response
Hello,
In my react React I've got an error when I first time enter the page:
THis may indicates that in my url there is no 'code' query. Indeed there is no 'code' query and after reloading the page it is.
I tried to change settings in my router:
Right now default page redirects to /dashboard. But even when I delete it doesn't work.
In TAuthConfig I have autoLogin: true and clearURL: false,
My expected behaviour - login wihout refreshing the page. Of course I can force login() method but it does not do the trick for me in this case
Changes that needs to be done:
If a user duplicates the tab / has multiple browser windows open with an application running react-oauth2-pkce
and the token expires, both tabs will try to refresh the token automatically. However, only one of them will succeed, for the second attempt, the refresh token will already have been consumed and therefore the refreshing doesn't work.
I am perfectly aware, this is likely an edge case, but it still generated quite some confusion among our users.
onRefreshTokenExpire
)I think this is related to the fact that tokens are stored in local storage which is shared across all tabs on the same domain. It's nice because the duplicated tab does not need to fetch a token on its own and can just use the one that's already in local storage but in the refresh case, it's odd. Basically, this is a race condition: Whichever instance of the application first attempts to refresh the token, will succeed and then cause all other instances to fail / prompt to reload the page.
From a user perspective, I would just expect the token to be silently refreshed of course - in all tabs. But on a more technical level, I am not sure how to best achieve it. It would either require cross-tabs communication or storing the tokens not in localStorage
but some tab specific storage like sessionStorage
.
Hey! I am using react 17 on my application and I noticed that after login, the ROCP_tokenExpire variable on localStorage has the right value of 1 hour, but the application will end the session within 10 minutes and navigate back to the authorization endpoint.
Looks like refreshAccessToken
method is using the stale values for tokenExpire and refreshTokenExpire, which is the default FALLBACK_EXPIRE_TIME.
Refreshing the page after authentication seems to solve the problem.
The option tokenExpiresIn
doesn't work as well.
I was able to fix it locally by setting the dependencies to useEffect, but would like to confirm if this is the best approach.
https://github.com/soofstad/react-oauth2-pkce/blob/main/src/AuthContext.tsx#L182
useEffect(() => {
interval = setInterval(() => refreshAccessToken(), 10000) // eslint-disable-line
return () => clearInterval(interval)
}, [token, tokenExpire, refreshToken, refreshTokenExpire, refreshInProgress])
ReactDOM.render(
<>
<div>
<h1>Demo using the 'react-oauth2-code-pkce' package</h1>
<p>
Github:{' '}
<a href="https://github.com/soofstad/react-oauth2-pkce">https://github.com/soofstad/react-oauth2-pkce</a>
</p>
<p>
NPM:{' '}
<a href="https://www.npmjs.com/package/react-oauth2-code-pkce">
https://www.npmjs.com/package/react-oauth2-code-pkce
</a>
</p>
</div>
<AuthProvider authConfig={softheonConfig}>
<LoginInfo />
</AuthProvider>
</>,
document.querySelector('#root')
)
The session ends in 10 minutes
The session must least for 1 hour
The idTokenData is not set.
{JSON.stringify(idTokenData, null, 2)} should show the payload of the id token.
See: b0ffedd#r109295837
Many auth providers supports or require the use of non-rfc standard parameters being sent in the authentication request.
We should support this by adding an extraAuthParams: {}
to the TAuthConfig and unpack that object with the auth request.
As you've already add a configuration to decide which storage to use, is it better to replace the sessionStorage in authentication
file with that configuration as well? The reason I'm saying so is that I have one use case:
Please take a consideration, thank you.
In my case, i need to pass same extra params into fetchTokens query, and on refetchToken. But with the current implementation of fetchWithRefreshToken function i can`t do it.
It will be great if you will add it.
Code that i write to do it
export const fetchWithRefreshToken = (props: {
config: TInternalConfig
refreshToken: string
}): Promise<TTokenResponse> => {
const { config, refreshToken } = props
const refreshRequest: TTokenRequestForRefresh = {
grant_type: 'refresh_token',
refresh_token: refreshToken,
scope: config.scope,
client_id: config.clientId,
redirect_uri: config.redirectUri,
...config.extraTokenParameters,
}
return postTokenRequest(config.tokenEndpoint, refreshRequest)
}
No response
No response
No response
No response
Hi guys.
Using Microsoft as a login provider, after the login we have a infinite loop when the page is redirected, even using the "cleanURL" param as true.
Configure your own clientId, and after the login you will see the infinite loop refresh, between microsoft and your application.
Got a peer dependency error. react@"17.0.2" I think it needs to be ^18.1.0? Was trying to install it on CRA, but it failed on resolve.
Hi,
Just wanted to share my expierence with AutoLogin.
So I was implementing the package as specified in the document where I encountered an issue with the autoLogin Param of this package.
What happens is that when we open our home page (in my case localhost:3000). Autologin which is set to TRUE redirects user to the required authentication point. But if the user after being redirecting, doesnot log in and tries to open home page again(localhost:3000), autoLogin fails to redirect him this time. The interesting thing is Now If the user refreshes his page (meaning that, he is loading the page for the third time), autoLogin will work and user will be redirected to the authentication point.
Summarizing, On Odd number of Page load count, autologin works. On even numbers, it doesnt.
Steps to replicate:
I replicated this using both of the examples given by you guyz on github but I changed the autoLogin to TRUE.
Provide the option to store all state used by the package in session storage.
This could be useful if developers want to force a new login on every new browser. For public/shared computers this could make sense.
react-oauth2-code-pkce
None specifically
No response
No response
It could be great if we had idTokenData in the useContext.
Today I have to reprocess the idToken decoding inside my react code.
It adds a few complexity when it could be done easily directly in the library as for tokenData.
The decoded idToken can be used for example to display the groups of the logged user.
interface IAuthContext {
// The access token. This is what you will use for authentication against protected API's
token: string
// An object with all the properties encoded in the token (username, email, etc.)
tokenData?: TTokenData
// Login the user
login: () => void
// Logout the user from the auth provider
logOut: () => void
// Keeps any errors that occured during login or token fetching/refreshing.
error: string | null
// The idToken, if it was returned along with the access token
idToken?: string
// An object with all the properties encoded in the ID token (username, groups, etc.)
idTokenData?: TTokenData
// If the <AuthProvider> is done fetching tokens or not. Usefull for controlling page rendering
loginInProgress: boolean
}
when using the library in an SharePoint Framework Webpart with React the bundle fails with a Webpack error:
./node_modules/react-oauth2-code-pkce/dist/AuthContext.js 77:19
Module parse failed: Unexpected token (77:19)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| function logOut() {
| clearStorage();
> if (config?.logoutEndpoint && refreshToken)
| (0, authentication_1.redirectToLogout)(config, refreshToken);
| }
@ ./node_modules/react-oauth2-code-pkce/dist/index.js 4:20-44
any ideas?
could there be an option to change this to href =
instead of replace
?
I am using autoLogin: false in my config, and navigating to the login on a button click. I'd like to be able to navigate back using browser back button after opening login page.
My OAuth provider uses id_token
as the JWT instead of token
, but react-oauth2-code-pkce
's AuthContext
tries to decode token
first, and fails immediately without getting to id_token
:
react-oauth2-pkce/src/AuthContext.tsx
Lines 121 to 126 in 4ada57f
react-oauth2-pkce/src/AuthContext.tsx
Lines 233 to 239 in 4ada57f
If they were decoded separately, I could at least use idTokenData
. My current workaround is to disable decodeToken
, and parse idToken
with my own decoder.
if (decodeToken) {
try {
setTokenData(decodeJWT(token))
} catch (e) {
setError((e as Error).message)
}
try {
if (idToken) setIdTokenData(decodeJWT(idToken))
} catch (e) {
setError((e as Error).message)
}
}
idToken
if (decodeToken) {
try {
setTokenData(decodeJWT(token))
} catch (e) {
setError((e as Error).message)
}
}
if (decodeIdToken) {
try {
if (idToken) setIdTokenData(decodeJWT(idToken))
} catch (e) {
setError((e as Error).message)
}
}
It potentially performs unnecessary work trying to decode token
when only idToken
is needed. If token
decoding fails, an error is shown in the browser console, which could annoy developers.
It's extra code/config to handle.
No response
No response
No response
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.