{"id":13989691,"url":"https://github.com/hasura/react-check-auth","last_synced_at":"2025-04-12T18:49:36.531Z","repository":{"id":57115327,"uuid":"130029321","full_name":"hasura/react-check-auth","owner":"hasura","description":"Add auth protection anywhere in your react/react-native app","archived":false,"fork":false,"pushed_at":"2023-02-21T15:16:01.000Z","size":456,"stargazers_count":541,"open_issues_count":8,"forks_count":43,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-04-14T11:41:36.701Z","etag":null,"topics":["authentication","npm-module","react","react-authentication"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hasura.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-04-18T08:24:12.000Z","updated_at":"2024-04-13T01:41:51.000Z","dependencies_parsed_at":"2024-01-14T20:16:54.818Z","dependency_job_id":"adb01c64-6838-4b9a-a52a-cff5469160e1","html_url":"https://github.com/hasura/react-check-auth","commit_stats":{"total_commits":40,"total_committers":7,"mean_commits":5.714285714285714,"dds":0.475,"last_synced_commit":"a91ef78a99a9b21c7105086289d2d503fefb0f07"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hasura%2Freact-check-auth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hasura%2Freact-check-auth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hasura%2Freact-check-auth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hasura%2Freact-check-auth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hasura","download_url":"https://codeload.github.com/hasura/react-check-auth/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248618218,"owners_count":21134199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","npm-module","react","react-authentication"],"created_at":"2024-08-09T13:01:57.732Z","updated_at":"2025-04-12T18:49:36.505Z","avatar_url":"https://github.com/hasura.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"## react-check-auth\n\n`react-check-auth` is a tiny react component that helps you make auth checks declarative in your react or react-native app.\n\nThis component uses [React 16's new context API](https://reactjs.org/docs/context.html) and is just ~100 LOC. It can also serve as a boilerplate for getting familiar with using the context API to pass information from a parent component to arbitrarily deep child components.\n\n## Motivation\n\nIn a typical app UI, depending on whether the user logs in, components in the application display different information.\n\nFor example, a \"welcome user\" label or a \"login button\" on a header. Or using this information with routing, `/home` should redirect to `/login` if the user is not logged in, and `/login` should redirect to `/home` if the user is logged in.\n\n### Before `react-check-auth`\n\n1. On load, your app must make a request to some kind of a `/verifyUser` or a `/fetchUser` endpoint to check if the existing persisted token/cookie is available and valid.\n2. You need to store that information in app state and pass it as a prop all through your component tree just so that that child components can access it or use `redux` to store the state and `connect()` the consuming component.\n\n### After `react-check-auth`\n\n1. You specify the `authUrl` endpoint as a prop to a wrapper component called `\u003cAuthProvider`.\n2. You access logged-in information by wrapping your react component/element in `\u003cAuthConsumer\u003e` that has the latest props.\n\nYou don't need to make an API request, or pass props around, or manage state/reducers/connections in your app.\n\n## Example\n\n### 1) Add AuthProvider\n\nWrap your react app in a `AuthProvider` component that has an endpoint to fetch basic user information. This works because if the user had logged in, a cookie would already be present. For using authorization headers, check the docs after the examples.\n\n```javascript\nimport React from \"react\";\nimport ReactDOM from \"react-dom\";\n\nimport {AuthProvider} from \"react-check-auth\";\nimport {Header, Main} from \"./components\";\n\nconst App = () =\u003e (\n  \u003cAuthProvider authUrl={'https://website.com/get/userInfo'}\u003e\n    \u003cdiv\u003e\n      // The rest of your react app goes here\n      \u003cHeader /\u003e\n      \u003cMain /\u003e\n    \u003c/div\u003e\n  \u003c/AuthProvider\u003e\n);\n\nReactDOM.render(\u003cApp /\u003e, document.getElementById(\"root\"));\n```\n\n### 2) Show a \"welcome user\" or a Login button\n\nNow, in any arbitrary component, like a Header, you can check if the user is currently logged in. Typically you would use this for either showing a \"welcome\" label or a login button.\n\n``` javascript\n  import {AuthConsumer} from 'react-check-auth';\n\n  const Header = () =\u003e (\n    \u003cdiv\u003e      \n      // Use the AuthConsumer component to check \n      // if userInfo is available\n      \u003cAuthConsumer\u003e \n        {({userInfo, isLoading, error}) =\u003e ( \n          userInfo ?\n            (\u003cspan\u003eHi {userInfo.username}\u003c/span\u003e) :\n            (\u003ca href=\"/login\"\u003eLogin\u003c/a\u003e)\n        )}\n       \u003c/AuthConsumer\u003e\n    \u003c/div\u003e\n  );\n```\n\n### 3) Redirect not-logged in users to /login\n\nYou can mix and match `react-check-auth` with other declarative components like routing:\n\n``` javascript\n  import {AuthConsumer} from 'react-check-auth';\n\n  const Main = () =\u003e (\n    \u003cRouter\u003e\n      \u003cRoute path='/home' component={Home} /\u003e\n      \u003cRoute path ='/login' component={Login} /\u003e\n    \u003c/Router\u003e\n   );\n   \n   const Home = () =\u003e {\n     return (\n       \u003cAuthConsumer\u003e\n         {({userInfo}) =\u003e {\n\n           // Redirect the user to login if they are not logged in\n           if (!userInfo) {\n              return (\u003cRedirect to='/login' /\u003e);\n           } \n           \n           // Otherwise render the normal component\n           else {\n             return (\u003cdiv\u003eWelcome Home!\u003c/div\u003e);\n           }\n         }}\n       \u003c/AuthConsumer\u003e\n     );\n   }\n);\n```\n\n\n## Usage guide\n\n### I. Backend requirements\n\nThese are the backend requirements that are assumed by `react-check-auth`.\n\n#### 1) API endpoint to return user information\n\nAn API request to fetch user information. It should take a cookie, or a header or a body for current session information.\n\nFor example:\n```http\nGET https://my-backend.com/api/user\nContent-Type: application/json\nCookie: \u003c...\u003e\nAuthorization: Bearer \u003c...\u003e\n```\n\n#### 2) Success or logged-in response\n\nIf the user is logged in, the API should return a `200` status code with a `JSON` object.\n\nFor example:\n```json\n{\n  \"username\": \"iamuser\",\n  \"id\": 123\n}\n```\n\n#### 3) Not logged-in response\n\nIf the user is not logged-in, the API should return a **non `200`** status code:\n\nFor example:\n```http\nStatus: 403\n```\n\n### II. Installation\n\n``` bash\n$ npm install --save react-check-auth\n```\n\n### III. Set up `AuthProvider`\n\nThe `AuthProvider` component should be at the top of the component tree so that any other component in the app can consume the `userInfo` information.\n\nThe `AuthProvider` takes a required prop called `authUrl` and an optional prop called `reqOptions`.\n\n```javascript\n\u003cAuthProvider authUrl=\"https://my-backend.com/api/user\" reqOptions={requestOptionsObject} /\u003e\n```\n\n##### `authUrl` :: String\nShould be a valid HTTP endpoint. Can be an HTTP endpoint of any method.\n\n\n##### `reqOptions` :: Object || Function\nShould be or return a valid `fetch` options object as per https://github.github.io/fetch/#options.\n\n**Note: This is an optional prop that does not need to be specified if your `authUrl` endpoint is a GET endpoint that accepts cookies.**\n\nDefault value that ensures cookies get sent to a `GET` endpoint:\n```json\n{ \n  \"method\": \"GET\",\n  \"credentials\": \"include\",\n  \"headers\": {\n    \"Content-Type\": \"application/json\"\n  },  \n}\n```\n\n#### Example 1: Use a GET endpoint with cookies\n\n``` javascript\n  import React from 'react';\n  import {AuthProvider} from 'react-check-auth';\n\n  const authUrl = \"https://my-backend.com/verifyAuth\";\n  \n  const App = () =\u003e (\n    \u003cAuthProvider authUrl={authUrl}\u003e\n      // The rest of your app goes here\n    \u003c/AuthProvider\u003e\n  );\n```\n\n#### Example 2: Use a GET endpoint with a header\n\n``` javascript\n  import React from 'react';\n  import {AuthProvider} from 'react-check-auth';\n\n  const authUrl = \"https://my-backend.com/verifyAuth\";\n  const reqOptions = { \n    'method': 'GET',\n    'headers': {\n      'Content-Type': 'application/json',\n      'Authorization' : 'Bearer ' + window.localStorage.myAuthToken\n    },  \n  }; \n  \n  const App = () =\u003e (\n    \u003cAuthProvider authUrl={authUrl} reqOptions={reqOptions}\u003e\n      // The rest of your app goes here\n    \u003c/AuthProvider\u003e\n  );\n```\n\n#### Example 3: Use a POST endpoint with updated token\n\n``` javascript\n  import React from 'react';\n  import {AuthProvider} from 'react-check-auth';\n\n  const authUrl = \"https://my-backend.com/verifyAuth\";\n  const reqOptions = () =\u003e { \n    'method': 'POST',\n    'headers': {\n      'Content-Type': 'application/json',\n      'Authorization' : 'Bearer ' + window.localStorage.myAuthToken\n    },  \n  }; \n  \n  const App = () =\u003e (\n    \u003cAuthProvider authUrl={authUrl} reqOptions={reqOptions}\u003e\n      // The rest of your app goes here\n    \u003c/AuthProvider\u003e\n  );\n```\n\n### IV. Consuming auth state with `\u003cAuthConsumer\u003e`\n\nAny react component or element can be wrapped with an `\u003cAuthConsumer\u003e` to consume the latest contextValue. You must write your react code inside a function that accepts the latest contextValue. Whenver the contextValue is updated then the AuthComponent is automatically re-rendered.\n\nFor example,\n```javascript\n\u003cAuthConsumer\u003e\n  {(props) =\u003e {\n    \n    props.userInfo = {..}        // \u003crequest-object\u003e returned by the API\n    props.isLoading = true/false // if the API has not returned yet\n    props.error = {..}           // \u003cerror-object\u003e if the API returned a non-200 or the API call failed\n  }}\n\u003c/AuthConsumer\u003e\n```\n\n##### `props.userInfo` :: JSON\n\nIf the API call returned a 200 meaning that the current session is valid, `userInfo` contains \u003crequest-object\u003e as returned by the API.\n\nIf the API call returned a non-200 meaning that the current session is absent or invalid, `userInfo` is set to `null`.\n\n##### `props.isLoading` :: Boolean\n\nIf the API call has not returned yet, `isLoading: true`. If the API call has not been made yet, or has completed then `isLoading: false`.\n\n\n##### `props.error` :: JSON\n\nIf the API call returned a non-200 or there was an error in making the API call itself, `error` contains the parsed JSON value.\n\n\n### V. Refresh state (eg: logout)\n\nIf you implement a logout action in your app, the auth state needs to be updated. All you need to do is call the `refreshAuth()` function available as an argument in the renderProp function of the `AuthConsumer` component.\n\nFor example:\n```javascript\n\n\u003cAuthConsumer\u003e\n  {(refreshAuth) =\u003e (\n    \u003cbutton onClick={{\n      this.logout() // This is a promise that calls a logout API\n        .then(\n          () =\u003e refreshAuth()\n        );\n    }}\u003e\n      Logout\n    \u003c/button\u003e\n\u003c/AuthConsumer\u003e  \n```\n\nThis will re-run the call to `authUrl` and update all the child components accordingly.\n\n### VI. Using with React Native\n\nUsage with React Native is exactly the same as with React. However you would typically use a Authorization header instead of cookies. Here's a quick example:\n\n``` javascript\n\nimport { AuthProvider, AuthConsumer } from 'react-vksci123';\n\nexport default class App extends Component\u003cProps\u003e {\n  render() {\n    const sessionToken = AsyncStorage.getItem(\"@mytokenkey\");\n    const reqOptions = {\n      \"method\": \"GET\",\n      \"headers\": sessionToken ? { \"Authorization\" : `Bearer ${sessionToken}` } : {}\n    }\n    return (\n      \u003cAuthProvider\n        authUrl={`https://my-backend.com/api/user`}\n        reqOptions={reqOptions}\n      \u003e\n        \u003cView style={styles.container}\u003e\n          \u003cText style={styles.welcome}\u003e\n            Welcome to React Native!\n          \u003c/Text\u003e\n          \u003cAuthConsumer\u003e\n            {({isLoading, userInfo, error}) =\u003e {\n              if (isLoading) {\n                return (\u003cActivityIndicator /\u003e);\n              }\n              if (error) {\n                return (\u003cText\u003e Unexpected \u003c/Text\u003e);\n              }\n              if (!userInfo) {\n                return (\u003cLoginComponent /\u003e);\n              }\n              return (\u003cHomeComponent /\u003e);\n            }}\n          \u003c/AuthConsumer\u003e\n        \u003c/View\u003e\n      \u003c/AuthProvider\u003e\n    );\n  }\n}\n\n```\n\n## Plug-n-play with existing auth providers\n\nAll Auth backend providers provide an endpoint to verify a \"session\" and fetch user information. This component was motivated from creating documentation for integrating Hasura's auth backend into a react app with minimum boilerplate. That said this package is meant to be used with any auth provider, including your own.\n\n### Hasura\n\nHasura's Auth API can be integrated with this module with a simple auth get endpoint  and can also be used to redirect the user to Hasura's Auth UI Kit in case the user is not logged in.\n\n```javascript\n  // replace CLUSTER_NAME with your Hasura cluster name.\n  const authEndpoint = 'https://auth.CLUSTER_NAME.hasura-app.io/v1/user/info';\n\n  // pass the above reqObject to CheckAuth\n  \u003cAuthProvider authUrl={authEndpoint}\u003e\n    \u003cAuthConsumer\u003e\n    { ({ isLoading, userInfo, error }) =\u003e { \n      // your implementation here\n    } }\n    \u003c/AuthConsumer\u003e\n  \u003c/AuthProvider\u003e\n```\n\nRead the docs here.\n\n### Firebase\n\n`CheckAuth` can be integrated with Firebase APIs.\n\n```javascript\n  // replace API_KEY with your Firebase API Key and ID_TOKEN appropriately.\n  const authUrl = 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/getAccountInfo?key=[API_KEY]';\n  const reqObject = { 'method': 'POST', 'payload': {'idToken': '[ID_TOKEN]'}, 'headers': {'content-type': 'application/json'}};\n\n  // pass the above reqObject to CheckAuth\n  \u003cAuthProvider authUrl={authUrl} reqObject={reqObject}\u003e\n    \u003cAuthConsumer\u003e\n    { ({ isLoading, userInfo, error }) =\u003e { \n      // your implementation here\n    } }\n    \u003c/AuthConsumer\u003e\n  \u003c/AuthProvider\u003e\n```\n\n### Custom Provider\n\n`CheckAuth` can be integrated with any custom authentication provider APIs.\n\nLets assume we have an endpoint on the backend `/api/check_token` which reads a header `x-access-token` from the request and provides with the associated user information\n\n```javascript\n  const authEndpoint = 'http://localhost:8080/api/check_token';\n  const reqOptions = { \n    'method': 'GET',\n    'headers': {\n      'Content-Type': 'application/json',\n      'x-access-token': 'jwt_token'\n    }\n  };\n\n  \u003cAuthProvider authUrl = { authEndpoint } reqOptions={ reqOptions }\u003e\n    \u003cAuthConsumer\u003e\n      { ( { isLoading, userInfo, error, refreshAuth }) =\u003e {\n        if ( !userInfo ) {\n          return (\n            \u003cspan\u003ePlease login\u003c/span\u003e\n          );\n        }\n        return (\n          \u003cspan\u003eHello { userInfo ? userInfo.username.name : '' }\u003c/span\u003e\n        );\n      }}\n    \u003c/AuthConsumer\u003e\n  \u003c/AuthProvider\u003e\n```\n\nIt will render as `\u003cspan\u003ePlease login\u003c/span\u003e` if the user's token is invalid and if the token is a valid one it will render \u003cspan\u003eHello username\u003c/span\u003e\n\n\n## How it works\n\n![How it works](./how-it-works.png?raw=true)\n\n1. The `AuthProvider` component uses the `authUrl` and `reqOptions` information given to it to make an API call\n2. While the API call is being made, it sets the context value to have `isLoading` to `true`.\n```json\n{\n  \"userInfo\": null,\n  \"isLoading\": true,\n  \"error\": null\n}\n```\n3. Once the API call returns, in the context value `isLoading` is set to `false' and:\n4. Once the API call returns, if the user is logged in, the AuthProvider sets the context to `userInfo: \u003cresponse-object\u003e`\n```json\n{\n  \"userInfo\": \u003cresponse-object\u003e,\n  \"isLoading\": false,\n  \"error\": null\n}\n```\n5. If the user is not logged in, in the context value, `userInfo` is set to `null` and `error` is set to the error response sent by the API, if the error is in JSON.\n```json\n{\n  \"userInfo\": null,\n  \"isLoading\": false,\n  \"error\": \u003cerror-response\u003e\n}\n```\n6. If the API call fails for some other reason, `error` contains the information\n\n```json\n{\n  \"userInfo\": null,\n  \"isLoading\": false,\n  \"error\": \u003cerror-response\u003e\n}\n```\n7. Whenever the contextValue is updated, any component that is wrapped with `AuthConsumer` will be re-rendered with the contextValue passed to it as an argument in the renderProp function:\n\n```javascript\n\u003cAuthConsumer\u003e\n  { ({userInfo, isLoading, error}) =\u003e {\n     return (...);\n  }}\n\u003cAuthConsumer\u003e\n```\n\n## Contributing\n\nClone repo\n\n````\ngit clone https://github.com/hasura/react-check-auth.git\n````\n\nInstall dependencies\n\n`npm install` or `yarn install`\n\nStart development server\n\n`npm start` or `yarn start`\n\nRuns the demo app in development mode.\n\nOpen [http://localhost:3000](http://localhost:3000) to view it in the browser.\n\n#### Source code\n\nThe source code for the react components are located inside `src/lib`.  \n\n#### Demo app\n\nA demo-app is located inside `src/demo` directory, which you can use to test your library while developing.\n\n#### Testing\n\n`npm run test` or `yarn run test`\n\n#### Build library\n\n`npm run build` or `yarn run build`\n\nProduces production version of library under the `build` folder.\n\n## Maintainers\n\nThis project has come out of the work at [hasura.io](https://hasura.io). \nCurrent maintainers [@Praveen](https://twitter.com/praveenweb), [@Karthik](https://twitter.com/k_rthik1991), [@Rishi](https://twitter.com/_rishichandra). \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhasura%2Freact-check-auth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhasura%2Freact-check-auth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhasura%2Freact-check-auth/lists"}