From 887f2bbddb9fe9e72ae1718ccbc77dea8ac4d40b Mon Sep 17 00:00:00 2001 From: Adrian Frith Date: Tue, 24 Sep 2019 21:15:35 +0200 Subject: [PATCH 1/4] Upgrade to new Context APi --- src/authenticated.js | 4 ++-- src/components/auth-context.js | 33 +++++++++++++++++---------------- src/components/token-manager.js | 4 ++-- src/context-types.js | 10 +++------- 4 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/authenticated.js b/src/authenticated.js index 6d1d618..31d1ea2 100644 --- a/src/authenticated.js +++ b/src/authenticated.js @@ -1,6 +1,6 @@ import React from 'react' import { getLocalToken } from './local-token' -import contextTypes from './context-types' +import AuthContextType from './context-types' export function hashed(o) { return Object @@ -31,6 +31,6 @@ export const authenticated = () => Component => { } } } - Authed.contextTypes = contextTypes + Authed.contextType = AuthContextType return Authed } diff --git a/src/components/auth-context.js b/src/components/auth-context.js index 5f2a8c6..4f395d9 100644 --- a/src/components/auth-context.js +++ b/src/components/auth-context.js @@ -1,5 +1,6 @@ import React from 'react' -import contextTypes from '../context-types' +import AuthContextType from '../context-types' +import PropTypes from 'prop-types' import { getHashValues } from '../lib/utils' import TokenManager from './token-manager' @@ -40,11 +41,6 @@ class Debug extends React.Component { } export class AuthContext extends React.Component { - getChildContext() { - const { provider, clientId, loggingInIndicator } = this.props - return { provider, clientId, loggingInIndicator } - } - isDebugEnabled = () => { return !!(localStorage.getItem('debug') || '').match(/react-u5auth/) } @@ -59,18 +55,23 @@ export class AuthContext extends React.Component { console.log('react-u5auth, debug', debug) return (
- { - this.setState({ token }) - onTokenUpdate && onTokenUpdate(token) - }} - /> - { debug && } - { showChildren && this.props.children } + + { + this.setState({ token }) + onTokenUpdate && onTokenUpdate(token) + }} + /> + { debug && } + { showChildren && this.props.children } +
) } } -AuthContext.propTypes = contextTypes -AuthContext.childContextTypes = contextTypes +AuthContext.propTypes = { + provider: PropTypes.string.isRequired, + clientId: PropTypes.string.isRequired, + loggingInIndicator: PropTypes.element +} diff --git a/src/components/token-manager.js b/src/components/token-manager.js index a8f67cc..566a329 100644 --- a/src/components/token-manager.js +++ b/src/components/token-manager.js @@ -1,6 +1,6 @@ import React from 'react' import { setLocalToken, getLocalToken, getLocalExpiresAt } from '../local-token' -import contextTypes from '../context-types' +import AuthContextType from '../context-types' import { hashed } from '../authenticated' import { getHashValues } from '../lib/utils' @@ -169,6 +169,6 @@ class TokenManager extends React.Component { } } -TokenManager.contextTypes = contextTypes +TokenManager.contextType = AuthContextType export default TokenManager diff --git a/src/context-types.js b/src/context-types.js index a39dd9f..b3edf67 100644 --- a/src/context-types.js +++ b/src/context-types.js @@ -1,9 +1,5 @@ -import PropTypes from 'prop-types' +import { createContext } from 'react' -const contextTypes = { - provider: PropTypes.string.isRequired, - clientId: PropTypes.string.isRequired, - loggingInIndicator: PropTypes.element -} +const AuthContextType = createContext() -export default contextTypes +export default AuthContextType From b246dd1ef6334de86341af314b4798c3819ec62d Mon Sep 17 00:00:00 2001 From: Adrian Frith Date: Tue, 24 Sep 2019 21:55:31 +0200 Subject: [PATCH 2/4] Move hashed() and authorize() into utils.js --- src/authenticated.js | 17 +---------------- src/components/token-manager.js | 2 +- src/lib/utils.js | 12 ++++++++++++ 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/authenticated.js b/src/authenticated.js index 31d1ea2..582ed7a 100644 --- a/src/authenticated.js +++ b/src/authenticated.js @@ -1,24 +1,9 @@ import React from 'react' import { getLocalToken } from './local-token' import AuthContextType from './context-types' - -export function hashed(o) { - return Object - .getOwnPropertyNames(o) - .map(prop => `${ prop }=${ encodeURIComponent(o[prop]) }`) - .join('&') -} +import { authorize } from './lib/utils' export const authenticated = () => Component => { - function authorize(provider, clientId) { - const query = { - client_id: clientId, - response_type: 'token', - redirect_uri: window.location - } - const url = `${ provider }/authorize?${ hashed(query) }` - window.location.replace(url) - } class Authed extends React.Component { render() { const token = getLocalToken() diff --git a/src/components/token-manager.js b/src/components/token-manager.js index 566a329..2b90bd6 100644 --- a/src/components/token-manager.js +++ b/src/components/token-manager.js @@ -1,7 +1,7 @@ import React from 'react' import { setLocalToken, getLocalToken, getLocalExpiresAt } from '../local-token' import AuthContextType from '../context-types' -import { hashed } from '../authenticated' +import { hashed } from '../lib/utils' import { getHashValues } from '../lib/utils' class TokenManager extends React.Component { diff --git a/src/lib/utils.js b/src/lib/utils.js index 8162bf2..b459306 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -1,4 +1,16 @@ +export const hashed = o => Object.getOwnPropertyNames(o) + .map(prop => `${ prop }=${ encodeURIComponent(o[prop]) }`) + .join('&') +export const authorize = (provider, clientId) => { + const query = { + client_id: clientId, + response_type: 'token', + redirect_uri: window.location + } + const url = `${ provider }/authorize?${ hashed(query) }` + window.location.replace(url) +} export const getHashValues = () => { const hash = window.location.hash From aef1d323a88b2dbe2edaf24996dce1e50f6efb68 Mon Sep 17 00:00:00 2001 From: Adrian Frith Date: Tue, 24 Sep 2019 21:55:50 +0200 Subject: [PATCH 3/4] Add useAuthentication() hook --- src/index.js | 3 ++- src/useAuthentication.js | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/useAuthentication.js diff --git a/src/index.js b/src/index.js index d66f8df..1b3a24d 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,6 @@ import { AuthContext } from './components/auth-context' import { authenticated } from './authenticated' +import { useAuthentication } from './useAuthentication' import { getLocalToken } from './local-token' -export { AuthContext, authenticated, getLocalToken } +export { AuthContext, authenticated, useAuthentication, getLocalToken } diff --git a/src/useAuthentication.js b/src/useAuthentication.js new file mode 100644 index 0000000..cb1c38b --- /dev/null +++ b/src/useAuthentication.js @@ -0,0 +1,16 @@ +import { useContext } from 'react' +import { getLocalToken } from './local-token' +import AuthContextType from './context-types' +import { authorize } from './lib/utils' + +export function useAuthentication() { + const token = getLocalToken() + const { clientId, provider } = useContext(AuthContextType) + + if (!token) { + authorize(provider, clientId) + return { authenticated: false } + } else { + return { authenticated: true, token } + } +} From 88739a3665527d20fb714938f3aa5b9616cee901 Mon Sep 17 00:00:00 2001 From: Adrian Frith Date: Tue, 24 Sep 2019 22:09:42 +0200 Subject: [PATCH 4/4] Add hook documentation to README --- README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/README.md b/README.md index 1da971f..452fd73 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,28 @@ const SomeOtherComponent = () => (

This is some other component

) const ProtectedComponent = authenticated()(() => ()) ``` +Instead of the higher-order function the hook `useAuthentication` can be used for the same purpose: + +```js +import { useAuthentication } from 'react-u5auth' + +const SomeComponent = () => ( +

Some component that needs an authenticated user...

+) + +const ProtectedComponent = () => { + const { authenticated } = useAuthentication() + + if (!authenticated) { + // This will appear only for a short time before the + // redirect to the auth provider URL kicks in. + return

Logging in...

+ } else { + return + } +} +``` + ## Using the `access_token` A protected component isn't too valuable on its own, you may need an access @@ -66,6 +88,13 @@ const token = getLocalToken() ... ``` +The `useAuthentication` hook also returns the token: + +```js +const { authenticated, token } = useAuthentication() +``` + + Please note: There is something fishy here about the `access_token` being kept in global state. See [this issue](https://github.com/Uber5/react-u5auth/issues/3).