Coder Social home page Coder Social logo

bhubr / react-simple-oauth2-login Goto Github PK

View Code? Open in Web Editor NEW
45.0 3.0 31.0 763 KB

Simple React component for OAuth2 login - Supports Authorization Code and Implicit Grant flows.

License: MIT License

HTML 1.23% JavaScript 85.23% EJS 13.54%
oauth2 react

react-simple-oauth2-login's Introduction

React Simple OAuth2 Login

All Contributors

๐Ÿ† Credits: this component is based on React GitHub Login by Checkr.

Simple React component for OAuth2 login.

Supports Authorization Code and Implicit Grant flows.

RTFM

Usage

Basic example

The component displays as a simple button. Clicking it will open the authorization screen for your chosen provider, in a popup (thus avoiding losing your app's state).

Four props are mandatory: authorizationUrl, responseType, clientId, redirectUri.

The client ID is given by the OAuth2 provider (usually along with a client secret) when you set up an OAuth2 app (where you're asked to fill in the Redirect URI).

import React from 'react';
import ReactDOM from 'react-dom';
import OAuth2Login from 'react-simple-oauth2-login';

const onSuccess = response => console.log(response);
const onFailure = response => console.error(response);

ReactDOM.render(
  <OAuth2Login
    authorizationUrl="https://accounts.spotify.com/authorize"
    responseType="token"
    clientId="9822046hvr4lnhi7g07grihpefahy5jb"
    redirectUri="http://localhost:3000/oauth-callback"
    onSuccess={onSuccess}
    onFailure={onFailure}/>,
  document.getElementById('root')
);

Example app

Check out the examples in the example directory. You'll need OAuth2 apps configured on whatever provider.

Client app

Setup:

  • cd example/client
  • npm install
  • Copy settings.sample.js as settings-code.js and/or settings-implicit.js, depending on which flow you intend to test.
  • npm start (uses Parcel)

The client app provides examples for both flows. If you look at the two components, what really distinguishes how they use the component is:

  • The value of responseType prop,
  • The fetch call to send the code to the server in the Authorization Code example.

Server app

The server app is only given as an example to test the Authorization Code flow. It currently supports getting access tokens from GitHub or Spotify. In a real-world app, you'll probably want to use Passport.

Right after you run npm install, you need to copy .env.sample as .env, and modify the values according to your needs.

  • OAUTH_TOKEN_URL is the URL where you should POST the code obtained from the authorization screen,
  • OAUTH_CLIENT_ID is the OAuth2 Client ID,
  • OAUTH_CLIENT_SECRET is the OAuth2 Client Secret,
  • OAUTH_REDIRECT_URI is the OAuth2 Redirect URI (thanks Captain Obvious).

The Client ID and Redirect URI should match that of the client app.

Then you can run npm start.

Cross Origin / Same-origin Policy

See the documentation on Same-origin policy

If you are using the Authorization Code flow, and your redirect URL is on a server with a different domain to your frontend, you will need to do the following:

  1. Set the isCrossOrigin property to true
  2. Set up your authorization url on your server to return a standard response similar to the one below:
<html>
<head></head>
<body>
  <script>
    window.addEventListener("message", function (event) {
      if (event.data.message === "requestResult") {
        event.source.postMessage({"message": "deliverResult", result: {...} }, "*");
      }
    });
  </script>
</body>
</html>

Your server needs to populate the result key with an object to deliver back to the frontend.

Props

authorizationUrl

{string} required

Base URL of the provider's authorization screen.

responseType

{string} required

Determines the type of OAuth2 flow. Two possible values:

  • code: Authorization Code flow. You need a server-side app to use this.
  • token: Implicit Grant flow.

clientId

{string} required

Client ID for OAuth application.

redirectUri

{string} required

Registered redirect URI for OAuth application.

scope

{string}

Scope for OAuth application. Example: user:email (GitHub).

popupWidth

{number}

Width for the popup window upon clicking the button in px. Default: 680.

popupHeight

{number}

Height for the popup window upon clicking the button in px. Default: 680.

className

{string}

CSS class for the login button.

buttonText

{string}

Text content for the login button.

isCrossOrigin

{bool}

Is this a cross-origin request? If you are implementing an Authorization Code workflow and your server backend is on a different URL, you'll need to set this to true.

extraParams

{object}

This allows you to pass extra query parameters to the OAuth2 login screen. Some providers allow additional parameters. See issue #39 on the repo for more details. If you want to add prompt=consent to the query string, you need to pass extraParams={{ prompt: 'consent' }} as a prop.

render

{function}

A custom rendering function. An object containing properties for rendering will be passed in as an argument, e.g. {buttonText: "...", children: [...], className: "...", onClick: func}.

onRequest

{function}

Callback for every request.

onSuccess

{function}

Callback for successful login. An object will be passed as an argument to the callback, e.g. { "code": "..." }.

onFailure

{function}

Callback for errors raised during login.

ChangeLog

  • v0.5.1 (published August 25th, 2021)

    • Allow to pass extra params in the query string, via the extraParams prop. Thanks to jshthornton
  • v0.5.0 (published June 18th, 2021)

    • Increase default popup's height. Thanks to tennox
    • Provide optional popupWidth and popupHeight props to override the defaults. Thanks to Coow
  • v0.4.0 (published June 18th, 2021)

    • Support cross-origin auth flow: previous versions worked only if the redirect URI was derived from the frontend app's URL; now you can have a redirect URI poiting to your backend app. Thanks (again) to rsnyman.
    • Update dev dependencies: ESLint, Enzyme
    • Restore unit tests to working state
    • End-to-end testing of Authorization Code flow (using a Node-based OAuth2 server)
  • v0.3.0 (Changes made in May, 2021 - published June 18th, 2021) - thanks to rsnyman for both additions:

    • Add render prop to customize the login button's appearance
    • Add MIT license
  • v0.2.0 (October 25th, 2020):

    • Add support for Implicit Grant flow
    • Improve error handling
    • Provide better example app (with a sample server-side app)
    • Try and provide a decent Readme
  • v0.1.x (January to September 2020th):

    • Spin the project off from React GitHub Login
    • Make it support various OAuth2 providers, only for Authorization Code flow

Contributors โœจ

Thanks goes to these wonderful people (emoji key):

Benoรฎt Hubert
Benoรฎt Hubert

๐Ÿ’ป ๐Ÿ“– ๐Ÿ’ก ๐Ÿšง โš ๏ธ
Raoul Snyman
Raoul Snyman

๐Ÿ’ป ๐Ÿ“–
Coow
Coow

๐Ÿ’ป
Manuel
Manuel

๐Ÿ› ๐Ÿ’ป
Stewart Park
Stewart Park

๐Ÿ’ป ๐Ÿ“–
Jure Sotosek
Jure Sotosek

๐Ÿ’ป
Joshua Thornton
Joshua Thornton

๐Ÿ’ป
Kalyan
Kalyan

๐Ÿ›
Alexandros Nikolopoulos
Alexandros Nikolopoulos

๐Ÿ›
Jacopo Rigoli
Jacopo Rigoli

๐Ÿ›

This project follows the all-contributors specification. Contributions of any kind welcome!

react-simple-oauth2-login's People

Contributors

allcontributors[bot] avatar bhubr avatar coow avatar dependabot[bot] avatar jshthornton avatar rsnyman avatar tennox avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

react-simple-oauth2-login's Issues

Cannot resolve dependency './settings-code' at '...\example\client\src\settings-code'

Running npm start in the example client folder returns

Server running at http://localhost:1234
ร—  react-simple-oauth2-login\example\client\src\AuthorizationCodeExample.js:11:7: Cannot resolve dependency './settings-code' at 'react-simple-oauth2-login\example\client\src\settings-code'
   9 |   oauthServerUrl,
  10 |   scope,
> 11 | } from './settings-code';
     |       ^
  12 |
  13 | export default function AuthorizationCodeExample() {
  14 |   const [accessToken, setAccessToken] = useState(null);

How can i fix this?

Adding additional query params breaks the client id

Google's authorization url let's you supply an additional query param of ?prompt=consent to force users to have to reauth every time.

If you supply that in the authorization url as such https://accounts.google.com/o/oauth2/v2/auth?prompt=consent then the client id is not appended and Google rejects with a malformed url error.

This can be bypassed by forcefully inserting the client id in the authorization url.

When using code response, DOMException is silenced

Note: I'm currently looking into this.

If you choose the "code" responseType (aka server-side) and your server is on a different domain to your React app, the popup window throws a DOMException "Blocked a frame with origin from access a cross-origin frame". This exception is then silenced in the popup window's poll() method.

There needs to be a better way to handle cross-origin requests. This is usually done through posting messages between the parent and child windows.

When I added to my project ,occured problem?

Hello , I added OAuth2Login to my project. I saw that problem. How to solve this problem

 ./node_modules/react-simple-oauth2-login/src/OAuth2Login.jsx 93:11
Module parse failed: Unexpected token (93:11)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process thi
s file. See https://webpack.js.org/concepts#loaders

    // eslint-disable-next-line react/jsx-props-no-spreading
>     return <button type="button" {...attrs}>{ children || buttonText }</button>;
   }
}


Prop for selecting redirect strategy

Add a prop to the Component to allow different methods when clicking the button. I.E: Popout (default now), new tab(_blank) & current window.

I might look into this myself in the near future if I have time

Not working with react 18+

It seems that the package has a dependency for react 16-17. Is this a matter of testing or are there breaking changes in react 18?

Not working with React 17.0.2

npm i react-simple-oauth2-login
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: [email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/react
npm ERR! react@"^17.0.2" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^16.0.0" from [email protected]
npm ERR! node_modules/react-simple-oauth2-login
npm ERR! react-simple-oauth2-login@"*" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!

"The popup was closed for an unexpected reason" popup is still open

I'm having an issue getting this working on my app. I've followed the example and the popup opens and retrieves a code from the auth endpoint, then redirects to http://localhost:3001/auth/redirect

The app is on http://localhost:3001/

I can't seem to see any other errors stopping it from returning correctly. It occurs on Chrome, Firefox, and Edge.

Any assistance would be appreciated

How to handle browsers that don't support popup read / postMessage

As mentioned in #20 (comment)

During testing I encountered some browsers which apparently lack all or some of the following:

  • popup URL tracking (like you use)
  • window.opener being set to the opening window (to communicate back)
  • window.postMessage (docs)

Examples of this:

Firefox Focus/Klar does not allow communication between tabs (at least I didn't get it to work)

MetaMask android (and many apps with in-app browser) (opens popup in separate browser app and thus allows no communication)

So I'm trying to figure out how to support those cases / provide a fallback.

Possible strategies:

Call server function in popup

Popup calls server & closes itself -> original window checks server for completion
This would work in any situation, even when the popup is opening a separate

Disadvantage: added complexity in backend is needed

Fallback to redirect flow

A redirect flow would work in all browsers as it stays in same window and just redirects back to the app.

Disadvantage: Needs app to know how to restore app state.
Problem: I don't see a way to detect whether to use this fallback reliably, and defaulting to it degrades UX for all other users.

Redirect URI is not encoded

When passing a redirectUri http://localhost:3000/#/oauth-callback/discord
The pop-up link generated by this lib is:
https://discord.com/oauth2/authorize?client_id=X&redirect_uri=http://localhost:3000/#/oauth-callback/discord&response_type=token

Discord will reject the request with the message: "Invalid redirect URI"

If I manually encode the URI and pass it to the React component, it works fine.

Improve docs & examples

Some things seem to be consistently confusing new users of the package:

  • How to specify scope: it is mentioned in the doc, but someone asked here. It should maybe be emphasized in some way in the docs.
  • How to use the examples: it's also mentioned in the readme, but there's this issue showing that it's not that clear. The settings-code.js and settings-implicit.js files are not included. Maybe we should go for a CRA-based version of the example, use env variables, and display warnings if some of the required ones are missing.

Tests don't work anymore ๐Ÿ˜ฑ

[benoit@mbp] ~/Code/react-simple-oauth2-login (master) $ npm test

> [email protected] test
> jest

Browserslist: caniuse-lite is outdated. Please run:
npx browserslist@latest --update-db
 FAIL  src/__tests__/OAuth2Login.test.js
  โ— Test suite failed to run

    Cannot find module 'react/lib/ReactComponentTreeHook' from 'ReactDebugTool.js'

    Require stack:
      node_modules/react-test-renderer/lib/ReactDebugTool.js
      node_modules/react-test-renderer/lib/ReactInstrumentation.js
      node_modules/react-test-renderer/lib/ReactReconciler.js
      node_modules/react-test-renderer/lib/ReactUpdates.js
      node_modules/react-test-renderer/lib/ReactDefaultBatchingStrategy.js
      node_modules/react-test-renderer/lib/ReactTestRenderer.js
      node_modules/react-test-renderer/index.js
      src/__tests__/OAuth2Login.test.js

      at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:299:11)
      at Object.<anonymous> (node_modules/react-test-renderer/lib/ReactDebugTool.js:14:30)

End-to-end testing

The existing tests, inherited from the original module, are too basic to be meaningful.

End-to-end testing would make future developments (OAuth2 + PKCE) safer.

onSucess when crossorigin

Hello everyone, thanks for the library first of all!

I'm working with a cross-origin request and I need to display the code from the response.

However, when I try it doesn't show up. If I set crossorigin to false I get an error in console about not being able to read the href from because of the cross-origin request. Nevertheless the code in that case is logged.

Has anyone encountered this before?

This is what I'm doing:
<OAuth2Login authorizationUrl="authUrl" responseType="code" clientId={clientId} redirectUri={redirectUri} onSuccess={(e) => console.log(e)} onFailure={(e) => console.log(e)} isCrossOrigin={true} //if false, the console.log works buttonText={"Login"} />

In addition to this, the behaviour that I have with isCrossOrigin=false is ideal, i don't have in reality any error in the behaviour, so I was wondeering why is the error message appearing in console

Support Auth Code + PKCE flow

[x] Basic support
[ ] Check state
[ ] Clear PKCE transient values in localStorage/sessionStorage
[x] Add example
[ ] Add example's sample config file
[ ] Document (new prop tokenUrl)
[ ] End-to-end testing
[ ] Ask for reviewers & testers

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.