React OAuth Flow
What is react-oauth-flow
react-oauth-flow
is a small library to simplify the use of OAuth2
authentication inside your react applications.
It will bring you a simple component to generate the necessary link to send your
users to the correct location and it will give you a component to perform the
authorization process once the user is back on your site.
Installation
npm install react-oauth-flow
yarn add react-oauth-flow
There is also a umd-build available for usage directly inside a browser, via
https://unkpg.com/react-oauth-flow/dist/react-oauth-flow.umd.min.js
.
<script src="https://unkpg.com/react-oauth-flow/dist/react-oauth-flow.umd.min.js"></script>
<script>
const { createOauthFlow, OauthSender, OauthReceiver } = ReactOauthFlow;
</script>
Requirements
react-oauth-flow
requires
fetch
to be
available on the window
-object. In modern browsers it's there by default. But
for older browsers you might need to provide it yourself as a polyfill.
If you are using
create-react-app
it's already included as a polyfill. Otherwise I recommend
whatwg-fetch
(which create-react-app
also
uses).
Usage
react-oauth-flow
exports three functions:
<OauthSender />
import React, { Component } from 'react';
import { OauthSender } from 'react-oauth-flow';
export default class SendToDropbox extends Component {
render() {
return (
<OauthSender
authorizeUrl="https://www.dropbox.com/oauth2/authorize"
clientId={process.env.CLIENT_ID}
redirectUri="https://www.yourapp.com/auth/dropbox"
state={{ from: '/settings' }}
render={({ url }) => <a href={url}>Connect to Dropbox</a>}
/>
);
}
}
Use <OauthSender />
to send your users to the correct endpoints at your OAuth2
service.
Props
Prop | Type | Required | Default | Description |
---|
authorizeUrl | string | yes | - | The full url to the authorize endpoint, provided by the service |
clientId | string | yes | - | Your client id from the service provider (remember to keep it secret!) |
redirectUri | string | yes | - | The URL where the provider should redirect your users back |
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 |
Render
<OauthSender />
can be used in three ways, either by a render-prop,
children-function or component-prop. In either way they will recieve the
generated url
as a prop/arg.
const RenderProp = props => (
<OauthSender {...props} render={({ url }) => <a href={url}>Connect</a>} />
);
const ChildrenFunction = props => (
<OauthSender {...props}>{({ url }) => <a href={url}>Connect</a>}</OauthSender>
);
const Link = ({ url }) => <a href={url}>Connect</a>;
const ComponentProp = props => <OauthSender {...props} component={Link} />;
State
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.
<OauthReceiver />
import React, { Component } from 'react';
import { OauthReceiver } from 'react-oauth-flow';
export default class ReceiveFromDropbox extends Component {
handleSuccess = async (accessToken, { response, state }) => {
console.log('Successfully authorized');
await setProfileFromDropbox(accessToken);
await redirect(state.from);
};
handleError = error => {
console.error('An error occured');
console.error(error.message);
};
render() {
return (
<OauthReceiver
tokenUrl="https://api.dropbox.com/oauth2/token"
clientId={process.env.CLIENT_ID}
clientSecret={process.env.CLIENT_SECRET}
redirectUri="https://www.yourapp.com/auth/dropbox"
onAuthSuccess={this.handleSuccess}
onAuthError={this.handleError}
render={({ processing, state, error }) => (
<div>
{processing && <p>Authorizing now...</p>}
{error && (
<p className="error">An error occured: {error.message}</p>
)}
</div>
)}
/>
);
}
}
Use <OauthReceiver />
to handle authorization when the user is being
redirected from the OAuth2-provider.
Props
Prop | Type | Required | Default | Description |
---|
tokenUrl | string | yes | - | The full url to the token endpoint, provided by the service |
clientId | string | yes | - | Your client id from the service provider (remember to keep it secret!) |
clientSecret | string | yes | - | Your client secret from the service provider (remember to keep it secret!) |
redirectUri | string | yes | - | The URL where the provider has redirected your user (used to verify auth) |
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) |
appName | string | no | react-oauth-flow | App name mainly used to provide a decent User-Agent header on token-request |
Events
onAuthSuccess(accessToken, result)
Arg | Type | Description |
---|
accessToken | string | Access token recieved from OAuth2 provider |
result | object | |
result.response | object | The full response from the call to the token-endpoint |
result.state | object | The state recieved from provider, if it was provided earlier |
Arg | Type | Description |
---|
error | Error | Error with message as description of what happened |
Render
<OauthReceiver />
can be used in three ways, either by a render-prop,
children-function 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 occured
const RenderProp = props => (
<OauthReceiver
{...props}
render={({ processing, state, error }) => (
<div>
{processing && <p>Authorization in progress</p>}
{state && <p>Will redirect you to {state.from}</p>}
{error && <p className="error">Error: {error.message}</p>}
</div>
)}
/>
);
const ChildrenFunction = props => (
<OauthReceiver {...props}>
{({ processing, state, error }) => (
<div>
{processing && <p>Authorization in progress</p>}
{state && <p>Will redirect you to {state.from}</p>}
{error && <p className="error">Error: {error.message}</p>}
</div>
)}
</OauthReceiver>
);
const View = ({ processing, state, error }) => (
<div>
{processing && <p>Authorization in progress</p>}
{state && <p>Will redirect you to {state.from}</p>}
{error && <p className="error">Error: {error.message}</p>}
</div>
);
const ComponentProp = props => <OauthReceiver {...props} component={View} />;
location
and querystring
The props location
and querystring
actually do the same thing but both can
be ommitted. But what they do is still important. When the OAuth2-provider
redirects your users back to your app they do so with a querystring attatched to
the call. <OauthReceiver />
parses this string to extract information that it
needs to request an access token.
location
is especially useful if you're using
react-router
. Because it
provides you with a location
-prop with all the information that
<OauthReceiver />
needs.
querystring
can be used if you want some control over the process, but
basically it's window.location.search
. So if it is not provided
<OauthReceiver />
will fetch the information from window.location.search
.
createOauthFlow
import { createOauthFlow } from 'react-oauth-flow';
const { Sender, Receiver } = createOauthFlow({
authorizeUrl: 'https://www.dropbox.com/oauth2/authorize',
tokenUrl: 'https://api.dropbox.com/oauth2/token',
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
redirectUri: 'https://www.yourapp.com/auth/dropbox',
});
export { Sender, Receiver };
createOauthFlow
is a shorthand to create instances of both <OauthSender />
and <OauthReceiver />
with equal settings to keep things DRY.
These instances can then be used as described above. All arguments can also be
overridden when you use the created components.
Args
Arg | Type | Required | Default | Description |
---|
options | object | yes | - | Options object |
options.authorizeUrl | string | yes | - | The full url to the authorize endpoint, provided by the service |
options.tokenUrl | string | yes | - | The full url to the token endpoint, provided by the service |
options.clientId | string | yes | - | Your client id from the service provider (remember to keep it secret!) |
options.clientSecret | string | yes | - | Your client secret from the service provider (remember to keep it secret!) |
options.redirectUri | string | yes | - | The URL where the provider should redirect your users back |
appName | string | no | react-oauth-flow | App name mainly used to provide a decent User-Agent header on token-request |
License
MIT
Contributors