{"id":24160472,"url":"https://github.com/simpleweb/redux-saga-oauth","last_synced_at":"2025-10-26T02:38:44.219Z","repository":{"id":33909901,"uuid":"91311396","full_name":"simpleweb/redux-saga-oauth","owner":"simpleweb","description":"👮 An OAuth module for Redux Saga powered applications","archived":false,"fork":false,"pushed_at":"2023-01-12T06:49:15.000Z","size":238,"stargazers_count":9,"open_issues_count":16,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-25T07:21:22.418Z","etag":null,"topics":["authentication","oauth2","react","react-native","redux","redux-saga"],"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/simpleweb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-05-15T08:07:40.000Z","updated_at":"2022-01-07T16:33:55.000Z","dependencies_parsed_at":"2023-01-15T03:31:12.069Z","dependency_job_id":null,"html_url":"https://github.com/simpleweb/redux-saga-oauth","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/simpleweb/redux-saga-oauth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simpleweb%2Fredux-saga-oauth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simpleweb%2Fredux-saga-oauth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simpleweb%2Fredux-saga-oauth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simpleweb%2Fredux-saga-oauth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simpleweb","download_url":"https://codeload.github.com/simpleweb/redux-saga-oauth/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simpleweb%2Fredux-saga-oauth/sbom","scorecard":{"id":825683,"data":{"date":"2025-08-11","repo":{"name":"github.com/simpleweb/redux-saga-oauth","commit":"246ac177d13e8f0ed2abc362a1f0faa51ae86d1e"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":7,"reason":"Found 12/17 approved changesets -- score normalized to 7","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 25 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"76 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v88g-cgmw-v5xw","Warn: Project is vulnerable to: GHSA-fwr7-v2mv-hh25","Warn: Project is vulnerable to: GHSA-42xw-2xvc-qx8m","Warn: Project is vulnerable to: GHSA-4w2v-q235-vp99","Warn: Project is vulnerable to: GHSA-cph5-m8f7-6c5x","Warn: Project is vulnerable to: GHSA-wf5p-g6vw-rhxx","Warn: Project is vulnerable to: GHSA-jr5f-v2jv-69x6","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-cwfw-4gq5-mrqx","Warn: Project is vulnerable to: GHSA-g95f-p29q-9xw4","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-9vvw-cc9w-f27h","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-hr2v-3952-633q","Warn: Project is vulnerable to: GHSA-h6ch-v84p-w6p9","Warn: Project is vulnerable to: GHSA-qrmc-fj45-qfc2","Warn: Project is vulnerable to: GHSA-74fj-2j2h-c42q","Warn: Project is vulnerable to: GHSA-pw2r-vq6v-hr8c","Warn: Project is vulnerable to: GHSA-jchw-25xp-jwwc","Warn: Project is vulnerable to: GHSA-cxjh-pqwp-8mfp","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-8r6j-v8pm-fqw3","Warn: Project is vulnerable to: MAL-2023-462","Warn: Project is vulnerable to: GHSA-xf7w-r453-m56c","Warn: Project is vulnerable to: GHSA-q42p-pg8m-cqh6","Warn: Project is vulnerable to: GHSA-w457-6q6x-cgp9","Warn: Project is vulnerable to: GHSA-62gr-4qp9-h98f","Warn: Project is vulnerable to: GHSA-f52g-6jhx-586p","Warn: Project is vulnerable to: GHSA-2cf5-4w76-r9qv","Warn: Project is vulnerable to: GHSA-3cqr-58rm-57f8","Warn: Project is vulnerable to: GHSA-g9r4-xpmj-mj65","Warn: Project is vulnerable to: GHSA-q2c6-c6pm-g3gh","Warn: Project is vulnerable to: GHSA-765h-qjxv-5f44","Warn: Project is vulnerable to: GHSA-f2jv-r9rf-7988","Warn: Project is vulnerable to: GHSA-44pw-h2cw-w3vq","Warn: Project is vulnerable to: GHSA-jp4x-w63m-7wgm","Warn: Project is vulnerable to: GHSA-c429-5p7v-vgjp","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-qqgx-2p2h-9c37","Warn: Project is vulnerable to: GHSA-2pr6-76vf-7546","Warn: Project is vulnerable to: GHSA-8j8c-7jfh-h6hx","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-fvqr-27wr-82fm","Warn: Project is vulnerable to: GHSA-4xc9-xhrj-v574","Warn: Project is vulnerable to: GHSA-x5rq-j2xg-h7qm","Warn: Project is vulnerable to: GHSA-jf85-cpcp-j695","Warn: Project is vulnerable to: GHSA-p6mc-m468-83gw","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-f9cm-qmx5-m98h","Warn: Project is vulnerable to: GHSA-7wpw-2hjm-89gp","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-vh95-rmgr-6w4m","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-w9mr-4mfr-499f","Warn: Project is vulnerable to: GHSA-5fw9-fq32-wv5p","Warn: Project is vulnerable to: GHSA-6394-6h9h-cfjg","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-6g33-f262-xjp4","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-2m39-62fm-q8r3","Warn: Project is vulnerable to: GHSA-mf6x-7mm4-x2g7","Warn: Project is vulnerable to: GHSA-j44m-qm6p-hp7m","Warn: Project is vulnerable to: GHSA-3jfq-g458-7qm9","Warn: Project is vulnerable to: GHSA-5955-9wpr-37jh","Warn: Project is vulnerable to: GHSA-f5x3-32g6-xq36","Warn: Project is vulnerable to: GHSA-jgrx-mgxx-jf9v","Warn: Project is vulnerable to: GHSA-g7q5-pjjr-gqvp","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-c4w7-xm78-47vh","Warn: Project is vulnerable to: GHSA-p9pc-299p-vxgp"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-23T16:35:40.725Z","repository_id":33909901,"created_at":"2025-08-23T16:35:40.726Z","updated_at":"2025-08-23T16:35:40.726Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276046873,"owners_count":25575876,"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","status":"online","status_checked_at":"2025-09-20T02:00:10.207Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","oauth2","react","react-native","redux","redux-saga"],"created_at":"2025-01-12T16:14:17.864Z","updated_at":"2025-09-20T04:32:01.564Z","avatar_url":"https://github.com/simpleweb.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# redux-saga-oauth\n\n[![NPM](https://img.shields.io/npm/v/@simpleweb/redux-saga-oauth.svg)](https://www.npmjs.com/package/@simpleweb/redux-saga-oauth)\n[![Build Status](https://semaphoreci.com/api/v1/projects/80e0a632-ac8f-4dc6-bfca-10565b56f6f8/1319097/badge.svg)](https://semaphoreci.com/simpleweb/redux-saga-oauth)\n\n👮 An OAuth module for Redux Saga powered applications\n\n## What does it do?\n\nRedux Saga OAuth provides a reducer and a saga to handle authentication within\nany JavaScript application that uses Redux and Redux Saga.\n\n### Key features\n\n* Has Flow support for easier integration\n* Handles all HTTP requests with [axios](https://github.com/mzabriskie/axios)\n* Allows for any grant types and extra data to be passed during login\n* Automatically handles token refresh following the standard flow\n* Handles failures during the refresh flow and will retry until it succeeds\n* Allows the refresh token to be expired on the server and log users out\n\n## Getting started\n\n### Install\n\nYou can install this via `yarn` or `npm`, however, `yarn` is the preferred\nmethod.\n\n```\nyarn add @simpleweb/redux-saga-oauth\n```\n```\nnpm install --save @simpleweb/redux-saga-oauth\n```\n\nIt also has a peer dependency of `redux-saga`, please make sure this is\ninstalled before hand.\n\n### Usage\n\n#### Add the provided reducer to your store\n\nWithin your existing Redux store, bring in the provided reducer. It’s key\n(`auth` in the example below) can be customised to anything you like.\n\n```js\nimport { Reducer } from \"@simpleweb/redux-saga-oauth\";\n\n\nconst store = createStore(\n  combineReducers({\n    auth: Reducer,\n  })\n);\n```\n\n#### Add the provided saga to your root saga\n\nCreate the provided auth saga and add it to your root saga. These are the\nrequired options you must pass. The `reducerKey` should match the key from\nthe step above.\n\n```js\nimport { createOAuthSaga } from \"@simpleweb/redux-saga-oauth\";\n\nconst authSaga = createOAuthSaga({\n  reducerKey: \"auth\",\n  OAUTH_URL: \"http://localhost:3000/oauth/token.json\",\n  OAUTH_CLIENT_ID: \"\u003cCLIENT ID\u003e\",\n  OAUTH_CLIENT_SECRET: \"\u003cCLIENT SECRET\u003e\",\n});\n\nconst sagas = function* rootSaga() {\n  yield all([\n    fork(authSaga),\n  ]);\n}\n```\n\n#### Login and logout\n\nTo login, simply import the provided actions, pass through your API’s\ncorresponding credentials and dispatch the action.\n\n```js\nimport { login, logout } from \"@simpleweb/redux-saga-oauth\";\n\nconst params = {\n  username: \"ben@simpleweb.co.uk\",\n  password: \"mysecurepassword\",\n  grant_type: \"password\",\n};\n\nstore.dispatch(\n  login(params)\n);\n\nstore.dispatch(\n  logout()\n);\n```\n\n#### Actions\n\nThe module does expose all it’s internal Redux actions and constants should you\nneed them. They are exposed like so.\n\n```js\nimport { Actions } from \"@simpleweb/redux-saga-oauth\";\n\nActions.authLoginRequest()\nActions.AUTH_LOGIN_REQUEST\n```\n\n#### Authenticated requests\n\nThis will something you _will_ want to do after having got this working, while\nthe code is not directly provided in the module, it's worth moving this into\nyour own codebase as some sort of helper function to make authenticated\nrequests using the access token in the store.\n\nPlease note any `import`’s are missing from the code below.\n\n`App/Sagas/AuthenticatedRequest.js`\n\n```js\n// Custom error type to be thrown from this saga\n// e.g. throw new AuthenticationSagaError('Some message');\nfunction AuthenticationSagaError(message) {\n  this.message = message;\n  this.name = \"AuthenticationSagaError\";\n}\n\n// Helper function to get the authentication state from the store\n// the \"authentication\" key will be unique to your code\nconst getAuthentication = state =\u003e state.auth;\n\n// Helper function to check if the token has expired\nexport const tokenHasExpired = ({ expiresIn, createdAt }) =\u003e {\n  const MILLISECONDS_IN_MINUTE = 1000 * 60;\n\n  // Set refreshBuffer to 10 minutes\n  // so the token is refreshed before expiry\n  const refreshBuffer = MILLISECONDS_IN_MINUTE * 10;\n\n  // Expiry time\n  // multiplied by 1000 as server time are return in seconds, not milliseconds\n  const expiresAt = new Date((createdAt + expiresIn) * 1000).getTime();\n  // The current time\n  const now = new Date().getTime();\n  // When we want the token to be refreshed\n  const refreshAt = expiresAt - refreshBuffer;\n\n  return now \u003e= refreshAt;\n};\n\n// Helper function to get the access token from the store\n// if the token has expired, it will wait until the token has been refreshed\n// or an authentication invalid error is thrown\nfunction* getAccessToken() {\n  const authentication = yield select(getAuthentication);\n\n  // Expires_in, created_at\n\n  // If the token has expired, wait for the refresh action\n  if (\n    tokenHasExpired({\n      expiresIn: authentication.expires_in,\n      createdAt: authentication.created_at,\n    })\n  ) {\n    yield race({\n      refreshError: take(AUTH_INVALID_ERROR),\n      tokenRefreshed: take(AUTH_REFRESH_SUCCESS),\n    });\n  }\n\n  // Return the latest access token\n  const latestAuthentication = yield select(getAuthentication);\n  return latestAuthentication.access_token;\n}\n\n// Finally the function you’ll use inside your sagas to make requests\nexport default function* AuthenticatedRequest(...args) {\n  // Get the current access token, wait for it if it needs refreshing\n  const accessToken = yield getAccessToken();\n\n  if (accessToken) {\n    const config = {\n      headers: {\n        Authorization: `Bearer ${accessToken}`,\n      },\n    };\n\n    try {\n      return yield call(...args, config);\n    } catch (error) {\n      if (error.response \u0026\u0026 error.response.status === 401) {\n        yield put(authInvalidError(error.response));\n        throw new AuthenticationSagaError(\"Unauthorized\");\n      } else {\n        throw error;\n      }\n    }\n  } else {\n    throw new AuthenticationSagaError(\"No access token\");\n  }\n}\n```\n\n##### Usage\n\nThe `AuthenticatedRequest` function simply wraps your normally API calls so\nadditional headers can be passed down to add in the access token.\n\n```js\nimport axios from \"axios\";\nimport AuthenticatedRequest from \"App/Sagas/AuthenticatedRequest\";\n\nfunction* MakeRequest() {\n  try {\n    const response = yield AuthenticatedRequest(axios.get, \"/user\");\n  } catch(error) {\n\n  }\n}\n```\n\n## Development\n\nYou can test this locally by installing it’s dependencies and linking it as a\nlocal module.\n\n```\ngit clone git@github.com:simpleweb/redux-saga-oauth.git\ncd redux-saga-oauth\nyarn \u0026\u0026 yarn link\n```\n\n## Deployment\n\nIncrement the `version` inside of the `package.json` and create a commit stating\na new version has been created, e.g. \"🚀 Released 1.0.0\".\n\nOn Github,\n[draft a new release](https://github.com/simpleweb/redux-saga-oauth/releases/new)\n, set the version and release title to \"vX.X.X\" (the version number that you\nwant to release) and add a description of the new release.\n\nNow run `yarn publish --access=public` to deploy the code to npm.\n\n## TL;DR\n\n![](https://media.giphy.com/media/12OIWdzFhisgww/giphy.gif)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimpleweb%2Fredux-saga-oauth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimpleweb%2Fredux-saga-oauth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimpleweb%2Fredux-saga-oauth/lists"}