{"id":26009946,"url":"https://github.com/byu-oit/byu-wabs-oauth","last_synced_at":"2026-02-14T02:03:15.528Z","repository":{"id":5283414,"uuid":"52975274","full_name":"byu-oit/byu-wabs-oauth","owner":"byu-oit","description":"Convenience library to handle oauth requests specific to BYU's well-known configuration data","archived":false,"fork":false,"pushed_at":"2025-02-12T18:52:46.000Z","size":168,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":28,"default_branch":"master","last_synced_at":"2025-09-28T09:28:59.341Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/byu-oit.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-03-02T15:48:58.000Z","updated_at":"2025-02-12T18:22:54.000Z","dependencies_parsed_at":"2024-06-21T02:12:15.724Z","dependency_job_id":"9b8d75f5-9456-4351-b4f5-c6d6adaa729e","html_url":"https://github.com/byu-oit/byu-wabs-oauth","commit_stats":{"total_commits":102,"total_committers":13,"mean_commits":7.846153846153846,"dds":"0.43137254901960786","last_synced_commit":"4c546195987d5cdd3d88ae2b654159ddafea57b5"},"previous_names":["byu-oit-appdev/byu-wabs-oauth"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/byu-oit/byu-wabs-oauth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/byu-oit%2Fbyu-wabs-oauth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/byu-oit%2Fbyu-wabs-oauth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/byu-oit%2Fbyu-wabs-oauth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/byu-oit%2Fbyu-wabs-oauth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/byu-oit","download_url":"https://codeload.github.com/byu-oit/byu-wabs-oauth/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/byu-oit%2Fbyu-wabs-oauth/sbom","scorecard":{"id":260503,"data":{"date":"2025-08-11","repo":{"name":"github.com/byu-oit/byu-wabs-oauth","commit":"76e30612b64c3171df51567eb4ed0943d8232ac7"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","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":"Code-Review","score":1,"reason":"Found 3/18 approved changesets -- score normalized to 1","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":"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":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/byu-oit/byu-wabs-oauth/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/byu-oit/byu-wabs-oauth/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:55: update your workflow using https://app.stepsecurity.io/secureworkflow/byu-oit/byu-wabs-oauth/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:60: update your workflow using https://app.stepsecurity.io/secureworkflow/byu-oit/byu-wabs-oauth/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:67: update your workflow using https://app.stepsecurity.io/secureworkflow/byu-oit/byu-wabs-oauth/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:81: update your workflow using https://app.stepsecurity.io/secureworkflow/byu-oit/byu-wabs-oauth/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:84: update your workflow using https://app.stepsecurity.io/secureworkflow/byu-oit/byu-wabs-oauth/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/byu-oit/byu-wabs-oauth/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/byu-oit/byu-wabs-oauth/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:59: update your workflow using https://app.stepsecurity.io/secureworkflow/byu-oit/byu-wabs-oauth/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:72: update your workflow using https://app.stepsecurity.io/secureworkflow/byu-oit/byu-wabs-oauth/codeql-analysis.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/ci.yml:73","Warn: npmCommand not pinned by hash: .github/workflows/ci.yml:41","Info:   0 out of   9 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned","Info:   0 out of   2 npmCommand dependencies pinned"],"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/ci.yml:49","Info: jobLevel 'actions' permission set to 'read': .github/workflows/ci.yml:50","Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql-analysis.yml:28","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql-analysis.yml:29","Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/codeql-analysis.yml:1","Info: no jobLevel write permissions found"],"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":"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":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"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: Apache License 2.0: 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":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"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":7,"reason":"SAST tool detected but not run on all commits","details":["Info: SAST configuration detected: CodeQL","Warn: 0 commits out of 17 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"}}]},"last_synced_at":"2025-08-17T10:44:04.329Z","repository_id":5283414,"created_at":"2025-08-17T10:44:04.329Z","updated_at":"2025-08-17T10:44:04.329Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29431593,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-13T22:20:51.549Z","status":"online","status_checked_at":"2026-02-14T02:00:07.626Z","response_time":53,"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":[],"created_at":"2025-03-05T22:26:35.360Z","updated_at":"2026-02-14T02:03:15.509Z","avatar_url":"https://github.com/byu-oit.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# byu-wabs-oauth\n\nManage OAuth client grant and auth code grant access tokens for BYU's implementation of WSO2.\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Examples](#examples)\n    - [Client Grant Token](#client-grant-token)\n    - [Code Grant Token](#code-grant-token)\n- [Create a BYU OAuth object](#create-a-byu-oauth-object)\n- [BYU OAuth Object](#byu-oauth-object)\n    - [getAuthorizationUrl](#getauthorizationurl)\n    - [getClientGrantToken](#getclientgranttoken)\n    - [getAuthCodeGrantToken](#getauthcodegranttoken)\n    - [refreshToken](#refreshtoken)\n    - [revokeToken](#revoketoken)\n- [BYU OAuth Token](#byu-oauth-token)\n- [Testing](#testing)\n\n## Installation\n\n```sh\n$ npm install byu-wabs-oauth\n```\n\n## Examples\n\n### Client Grant Token\n\nUse this grant type for communicating from one server to another where a specific user’s permission to access data is\nnot required.\n\n```js\nconst byuOAuth = require('byu-wabs-oauth')\n\n;(async function () {\n  const oauth = await byuOAuth('\u003cclient_id\u003e', '\u003cclient_secret\u003e')\n  const token = await oauth.getClientGrantToken()\n})()\n```\n\n### Auth Code Grant Token\n\nUse this grant type if you need the user's authorization to access data. Getting this grant type is a two step process.\n\n1. Direct the user to the authorization URL\n2. Get the token using the authorization code that comes in a follow up request\n\n```js\nconst byuOAuth = require('byu-wabs-oauth')\nconst querystring = require('querystring')\nconst redirectUrl = 'http://localhost:3000/'\n\n// start a server that will listen for the OAuth code grant redirect\nconst server = http.createServer(async (req, res) =\u003e {\n  const oauth = await byuOAuth('\u003cclient_id\u003e', '\u003cclient_secret\u003e')\n  const qs = querystring.parse(req.url.split('?')[1] || '')\n\n  // if there is no code then redirect browser to authorization url\n  if (!qs.code) {\n    const url = await oauth.getAuthorizationUrl(redirectUrl)\n    res.setHeader('Location', url)\n    res.end()\n\n    // if there is a code then use the code to get the code grant token\n  } else {\n    const token = await oauth.getCodeGrantToken(qs.code, redirectUrl)\n    res.write(token.accessToken)\n    res.end()\n  }\n});\n\nconst listener = server.listen(3000)\n```\n\n## Create a BYU OAuth object\n\n`byuWabsOAuth (clientId: string, clientSecret: string, options: ByuJWT.Options) : Promise\u003cByuOAuth\u003e`\n\n**Parameters**\n\n| Parameter        | Type             | Required | Description                                                                                                                  |\n|------------------|------------------|----------|------------------------------------------------------------------------------------------------------------------------------|\n| **clientId**     | `string`         | Yes      | The client ID or consumer key                                                                                                |\n| **clientSecret** | `string`         | Yes      | The client secret or consumer secret                                                                                         |\n| **options**      | `ByuJWT.Options` | No       | The [ByuJWT Options](https://github.com/byu-oit/byu-jwt-nodejs/blob/8d3fe95170c7b2f1a149e29c8123946586d3daa4/index.d.ts#L12) |\n\n**Returns** a Promise that resolves to an object with the following methods and properties:\n\nMethods:\n\n- [getAuthorizationUrl](#getauthorizationurl) - Get the URL that will provide an OAuth code grant code.\n- [getClientGrantToken](#getclientgranttoken) - Get a client grant [token](#byu-oauth-token). Use this grant type for\n  communicating from one server to another where a specific user’s permission to access data is not required.\n- [getAuthCodeGrantToken](#getauthcodegranttoken) - Get a code grant [token](#byu-oauth-token). Use this grant type if\n  you need the user's authorization to access data.\n- [refreshToken](#refreshtoken) - Use a refresh token to get a new [token](#byu-oauth-token) object.\n- [revokeToken](#revoketoken) - Use to revoke an access token and / or refresh token.\n\nProperties:\n\n- authorizationEndpoint\n- idTokenSigningAlgorithmValuesSupported\n- issuer\n- jwksUri\n- responseTypesSupported\n- revocationEndpoint\n- scopesSupported\n- subjectTypesSupported\n- tokenEndpoint\n- userInfoEndpoint\n\n**Example**\n\n```js\nconst byuOAuth = require('byu-wabs-oauth')\nconst oauth = await byuOauth('\u003cclient_id\u003e', '\u003cclient_secret\u003e')\n```\n\n### getAuthorizationUrl\n\n`getAuthorizationUrl ( redirectUri: string [, state: string ] ): Promise\u003cstring\u003e`\n\nGet the URL that needs to be visited to acquire an auth code grant code.\n\n**Parameters**\n\n| Parameter       | Type     | Required | Description                                                                                                |\n|-----------------|----------|----------|------------------------------------------------------------------------------------------------------------|\n| **redirectUri** | `string` | Yes      | The URL that the API manager will redirect to after the user has authorized the application.               |\n| state           | `string` | No       | State information to add to the URL. You can read this state information when the `redirectUri` is called. |\n\n**Returns** a Promise that resolves to the URL.\n\n**Example**\n\n```js\n;(async () =\u003e {\n  const byuOAuth = require('byu-wabs-oauth')\n  const oauth = await byuOauth('\u003cclient_id\u003e', '\u003cclient_secret\u003e')\n\n  const url = await oauth.getAuthorizationUrl('https://my-server.com', 'state info')\n})()\n```\n\n### getClientGrantToken\n\n`getClientGrantToken (): Promise\u003cToken\u003e`\n\nGet a client grant [token](#byu-oauth-token).\n\n**Parameters**\n\nNone\n\n**Returns** a Promise that resolves to a [token](#byu-oauth-token).\n\n**Example**\n\n```js\n;(async () =\u003e {\n  const byuOAuth = require('byu-wabs-oauth')\n  const oauth = await byuOauth('\u003cclient_id\u003e', '\u003cclient_secret\u003e')\n\n  const token = await oauth.getClientGrantToken()\n})()\n```\n\n### getAuthCodeGrantToken\n\n`getAuthCodeGrantToken ( code: string, redirectUri: string): Promise\u003cToken\u003e`\n\nGet a code grant [token](#byu-oauth-token).\n\n**Parameters**\n\n| Parameter       | Type     | Required | Description                                                                                       |\n|-----------------|----------|----------|---------------------------------------------------------------------------------------------------|\n| **code**        | `string` | Yes      | The code grant code that signifies authorization                                                  |\n| **redirectUri** | `string` | Yes      | The original URI specified when calling the [getAuthorizationUrl](#getauthorizationurl) function. |\n\n**Returns** a Promise that resolves to a [token](#byu-oauth-token).\n\n**Example**\n\nSee the [Code Grant Token example](#code-grant-token).\n\n### refreshToken\n\n`refreshToken ( refreshToken: string ): Promise\u003cToken\u003e`\n\nGet a new access token using a refresh token.\n\n**Parameters**\n\n| Parameter        | Type     | Required  | Description                   |\n|------------------|----------|-----------|-------------------------------|\n| **accessToken**  | `string` | Yes       | The access token to refresh.  |\n| **refreshToken** | `string` | Yes       | The associated refresh token. |\n\n**Returns** a Promise that resolves to a [token](#byu-oauth-token).\n\n**Example**\n\n```js\n;(async () =\u003e {\n  const byuOAuth = require('byu-wabs-oauth')\n  const oauth = await byuOauth('\u003cclient_id\u003e', '\u003cclient_secret\u003e')\n\n  const token = await oauth.refreshToken('\u003caccess_token\u003e', '\u003crefresh_token\u003e')\n})()\n```\n\n### revokeToken\n\n`revokeToken ( accessToken: string [, refreshToken: string ] ): Promise\u003cvoid\u003e`\n\nRevoke an access token and / or a refresh token.\n\n**Parameters**\n\n| Parameter       | Type     | Required | Default | Description                                  |\n|-----------------|----------|----------|---------|----------------------------------------------|\n| **accessToken** | `string` | Yes      | N/A     | The access token to revoke.                  |\n| refreshToken    | `string` | No       | N/A     | The associated refresh token to also revoke. |\n\n**Returns** a Promise that resolves to undefined.\n\n**Example**\n\n```js\n;(async () =\u003e {\n  const byuOAuth = require('byu-wabs-oauth')\n  const oauth = await byuOauth('\u003cclient_id\u003e', '\u003cclient_secret\u003e')\n  await oauth.revokeToken('\u003caccess_token\u003e', '\u003crefresh_token\u003e')\n})()\n```\n\n## BYU OAuth Token\n\nThis object has information about the current token as well as methods for managing the token. These are the properties:\n\n- accessToken - A string that has the most recent access token. This value will be `undefined` if the token has been\n  revoked.\n- expiresAt - A Date object that represents when the token will expire.\n- expiresIn - The number of milliseconds until the token expires.\n- refreshToken - A string representing the refresh token. This value will be `undefined` for client grant tokens,\n  although client grant tokens can still be refreshed using the `refresh` function on this object.\n- resourceOwner - Only valid for code grant tokens, this object contains the resource owner's properties:\n    - atHash: string\n    - aud: Array\u003cstring\u003e\n    - authTime: number\n    - azp: string\n    - byuId: string\n    - exp: number\n    - iat: number\n    - iss: string\n    - jwt: string\n    - netId: string\n    - personId: string\n    - preferredFirstName: string\n    - prefix: string\n    - restOfName: string\n    - sortName: string\n    - sub: string\n    - suffix: string\n    - surname: string\n    - surnamePosition: string\n- scope - A string representing the scopes associated with this token.\n- type - A string of the token type.\n\n## Testing\n\n#### Run the tests\n\n1. In the terminal, log into the BYU DevX AWS Account\n\n  ```shell\n  aws sso login --profile byu-oit-devx-prd\n  ```\n\n2. In this root of this project, run:\n\n  ```shell \n  npm install\n  npm test\n  ```\n\n#### Update environment variables used in the tests\n\n1. Create the file `./iac/vars.tfvars`.\n2. Copy this template into that file.\n\n  ```terraform\n  consumer_key  = \"\"\nconsumer_secret = \"\"\ncallback_url    = \"\"\nnet_id          = \"\"\npassword        = \"\"\n  ```\n\n3. Copy and paste the values from the parameter store into this file.\n4. Update the values you want to change.\n5. Set the AWS_PROFILE environment variable.\n\n  ```shell\n  export AWS_PROFILE=byu-oit-devx-prd\n  ```\n\n6. Login to the BYU DevX AWS Account.\n\n  ```shell\n  aws sso login --profile $AWS_PROFILE\n  ```\n\n7. From within the `./iac` directory, apply the changes in Terraform.\n\n\u003e Ensure you use same version of terraform (as of right now v1.2.2 is latest).\n\n  ```shell\n  terraform init\n  terraform apply --var-file vars.tfvars\n  ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbyu-oit%2Fbyu-wabs-oauth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbyu-oit%2Fbyu-wabs-oauth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbyu-oit%2Fbyu-wabs-oauth/lists"}