Simplifying authorization via OAuth2's Authorization Code Flow (and PKCE) via React Components
react-oauth2-auth-code-flow is a library of components to simplify the use of OAuth2's Authorization Code Grant specifically within [react]
applications in the context of Innoactive's Portal services.
This package builds upon the excellent react-oauth2-auth-code-flow components to:
- generate the necessary link to send users to the correct location to grant authorization
- obtain an access token once the user is back on your site
and uses client-oauth2 under the hood, thereby combining two very well-designed libraries.
This library also supports the PKCE extension, which is recommended for SPAs, out of the box.
using npm:
npm install --save react-oauth2-auth-code-flowusing yarn:
yarn add react-oauth2-auth-code-flowThis package currently depends on having a module bundler in place, i.e. there's no browser compatible version (umd) available.
react-oauth2-auth-code-flow exports two Components:
importReact,{Component}from"react";import{RequestAuthorizationCode}from"react-oauth2-auth-code-flow";importClientOAuth2from"client-oauth2";constoauthClient=newClientOAuth2({clientId: process.env.CLIENT_ID,clientSecret: process.env.CLIENT_SECRET,accessTokenUri: `${apiRoot}/oauth/token/`,authorizationUri: "https://www.dropbox.com/oauth2/authorize",redirectUri: "https://www.yourapp.com/auth/dropbox",scopes: ["read"],});exportdefaultclassSendToDropboxextendsComponent{render(){return(<RequestAuthorizationCodeoauthClient={oauthClient}state={{from: "/settings"}}render={({ url })=><ahref={url}>Connect to Dropbox</a>}/>);}}Use <RequestAuthorizationCode /> to send your users to the correct endpoints at your OAuth2
service.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
oauthClient | ClientOAuth2 | yes | - | An instance of the ClientOAuth2 library |
state | object | no | - | Additional state to get back from the service provider (read more below) |
args | object | no | - | Additional args to send to service provider, e.g. scope. Will be serialized by qs |
<RequestAuthorizationCode /> can be used in two ways, either by a render-prop,
or component-prop. In either way they will recieve the generated url as a prop/arg.
constRenderProp=(props)=>(<RequestAuthorizationCode{...props}render={({ url })=><ahref={url}>Connect</a>}/>);constLink=({ url })=><ahref={url}>Connect</a>;constComponentProp=(props)=>(<RequestAuthorizationCode{...props}component={Link}/>);You can pass some state along with the auth process. This state will be sent back by the OAuth-provider once the process is done. This state can for example then be used to redirect the user back to where they started the auth process.
importReact,{Component}from"react";import{AuthorizationCodeCallback}from"react-oauth2-auth-code-flow";importClientOAuth2from"client-oauth2";constoauthClient=newClientOAuth2({clientId: process.env.CLIENT_ID,clientSecret: process.env.CLIENT_SECRET,accessTokenUri: `${apiRoot}/oauth/token/`,authorizationUri: "https://www.dropbox.com/oauth2/authorize",redirectUri: "https://www.yourapp.com/auth/dropbox",scopes: ["read"],});exportdefaultclassReceiveFromDropboxextendsComponent{handleSuccess=async(accessToken,{ response, state })=>{console.log("Successfully authorized");awaitsetProfileFromDropbox(accessToken);awaitredirect(state.from);};handleError=(error)=>{console.error("An error occurred");console.error(error.message);};render(){return(<AuthorizationCodeCallbackoauthClient={oauthClient}onAuthSuccess={this.handleSuccess}onAuthError={this.handleError}render={({ processing, state, error })=>(<div>{processing&&<p>Authorizing now...</p>}{error&&(<pclassName="error">An error occurred: {error.message}</p>)}</div>)}/>);}}Use <AuthorizationCodeCallback /> to handle authorization when the user is being
redirected from the OAuth2-provider.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
oauthClient | ClientOAuth2 | yes | - | An instance of the ClientOAuth2 library |
args | object | no | - | Args will be attatched to the request to the token endpoint. Will be serialized by qz |
location | { search: string } | no | - | Used to extract info from querystring (read more below) |
querystring | string | no | - | Used to extract info from querystring (read more below) |
tokenFetchArgs | object | no | {} | Used to fetch the token endpoint (read more below) |
tokenFn | func | no | null | Used to bypass default fetch function to fetch the token (read more below) |
onAuthSuccess(accessToken, result)
| Arg | Type | Description |
|---|---|---|
accessToken | string | Access token recieved from OAuth2 provider |
result | object | |
result.response | object | The full token response from the call to the token-endpoint |
result.state | object | The state recieved from provider, if it was provided earlier |
onAuthError(error)
| Arg | Type | Description |
|---|---|---|
error | Error | Error with message as description of what happened |
<AuthorizationCodeCallback /> can be used in two ways, either by a render-prop or component-prop.
Either way they will recieve three props/args:
processing: boolean: True if authorization is in progressstate: object: The state received from provider (might be null)error: Error: An error object if an error occurred
constRenderProp=(props)=>(<AuthorizationCodeCallback{...props}render={({ processing, state, error })=>(<div>{processing&&<p>Authorization in progress</p>}{state&&<p>Will redirect you to {state.from}</p>}{error&&<pclassName="error">Error: {error.message}</p>}</div>)}/>);constView=({ processing, state, error })=>(<div>{processing&&<p>Authorization in progress</p>}{state&&<p>Will redirect you to {state.from}</p>}{error&&<pclassName="error">Error: {error.message}</p>}</div>);constComponentProp=(props)=>(<AuthorizationCodeCallback{...props}component={View}/>);--> see react-oauth-flow docs
--> see react-oauth-flow docs
--> see react-oauth-flow docs
- client-oauth2 for an excellent oauth2 base client implementation
- react-oauth2-auth-code-flow for inspriation how to support OAuth2's Authorization Code Flow with components