{"id":14482574,"url":"https://github.com/andreassolberg/jso","last_synced_at":"2025-05-15T09:04:10.114Z","repository":{"id":2669225,"uuid":"3660761","full_name":"andreassolberg/jso","owner":"andreassolberg","description":"Easy to use OAuth 2.0 javascript library for use in your javascript application.","archived":false,"fork":false,"pushed_at":"2024-01-18T06:04:38.000Z","size":1289,"stargazers_count":885,"open_issues_count":51,"forks_count":165,"subscribers_count":52,"default_branch":"master","last_synced_at":"2025-05-10T07:06:41.086Z","etag":null,"topics":["api","authentication","authorization","javascript","oauth2","sso"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andreassolberg.png","metadata":{"files":{"readme":"README.md","changelog":null,"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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2012-03-08T14:31:55.000Z","updated_at":"2025-05-01T11:55:02.000Z","dependencies_parsed_at":"2024-06-18T14:05:58.304Z","dependency_job_id":"2c11b66c-8b50-4a70-8934-0ca15e8aaed0","html_url":"https://github.com/andreassolberg/jso","commit_stats":{"total_commits":223,"total_committers":14,"mean_commits":"15.928571428571429","dds":"0.10313901345291476","last_synced_commit":"b1be102c5c8eedb15c38dea2ba56d83b749eed94"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreassolberg%2Fjso","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreassolberg%2Fjso/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreassolberg%2Fjso/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreassolberg%2Fjso/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andreassolberg","download_url":"https://codeload.github.com/andreassolberg/jso/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254310513,"owners_count":22049468,"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":["api","authentication","authorization","javascript","oauth2","sso"],"created_at":"2024-09-03T00:01:11.490Z","updated_at":"2025-05-15T09:04:10.066Z","avatar_url":"https://github.com/andreassolberg.png","language":"JavaScript","readme":"# JSO – OAuth 2.0 Client with Javascript\n\n[![Build Status](https://travis-ci.org/andreassolberg/jso.svg?branch=master)](https://travis-ci.org/andreassolberg/jso)\n\n\u003c!-- * [JSO Documentation](http://oauth.no/jso/) ---\u003e\n\nJSO is a simple and flexible OAuth javascript library to use in your web application or native mobile app.\n\nJSO is provided by [UNINETT AS](http://www.uninett.no), a non-profit company working for educational and research institutions in Norway.\n\n\n## Features\n\n\n* Implements **OAuth 2.0 Implicit Flow**.\n* Can also be used with **OpenID Connect**.\n* ES6 compatible loading via npm/webpack\n* Also included a UMD-bundled version in the `dist/` folder\n* No server component needed.\n* Can handle multiple providers at once.\n* Uses *HTML 5.0 localStorage* to cache Access Tokens. You do not need to implement a storage.\n* Can prefetch all needed tokens with sufficient scopes, to start with, then tokens can be used for requests later. This way, you can be sure that you would not need to redirect anywhere in your business logic, because you would need to refresh an expired token.\n* Excellent scope support.\n* Caches and restores the hash, your application will not loose state when sending the user to the authorization endpoint.\n* Provided with easy to use `fetch()` wrapper that takes care of all you need to get the token, and then returns the API data you want\n* Experimental feature: *OAuth 2.0 Authorization Code* flow.\n* Experimental feature: `Jquery.ajax()`-wrapper, if you have jquery loaded, and does not want to require or polyfill fetch\n\n\n\n## How to use\n\nInstall using npm:\n\n```bash\nnpm install jso --save\n```\n\nIf you use webpack or similar it is recommended to import the needed components like this:\n\n```javascript\nimport {JSO, Popup} from 'jso'\n\nlet config = {...}\nlet j = new JSO(config)\n```\n\nTo load the javascript, you could use the distributed UMD module:\n\n```html\n\u003cscript type=\"text/javascript\" src=\"dist/jso.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"text/javascript\"\u003e\n\tvar config = {...}\n\tvar j = new jso.JSO(config)\n\u003c/script\u003e\n```\n\nThe same bundle is available through CDN:\n\n```html\n\u003cscript type=\"text/javascript\" src=\"https://unpkg.com/jso/dist/jso.js\"\u003e\u003c/script\u003e\n```\n\n### Initializing the client\n\nTo start using JSO, you need to initialize a new JSO object with configuration for an OAuth 2.0 Provider:\n\n```javascript\nlet client = new JSO({\n\tproviderID: \"google\",\n\tclient_id: \"541950296471.apps.googleusercontent.com\",\n\tredirect_uri: \"http://localhost:8080/\", // The URL where you is redirected back, and where you perform run the callback() function.\n\tauthorization: \"https://accounts.google.com/o/oauth2/auth\",\n\tscopes: { request: [\"https://www.googleapis.com/auth/userinfo.profile\"]}\n})\n```\n\nOptions to JSO constructor\n\n* `providerID`: **OPTIONAL** This is just a name tag that is used to prefix data stored in the browser. It can be anything you'd like :)\n* `client_id`: **REQUIRED** The client idenfier of your client that is trusted by the provider. As JSO uses the implicit grant flow, there is no use for a client secret.\n* `authorization`: **REQUIRED** The authorization URL endpoint of the OAuth server\n* `redirect_uri`: **OPTIONAL** (may be needed by the provider). The URI that the user will be redirected back to when completed. This should be the same URL that the page is presented on.\n* `scopes.require`: Control what scopes are required in the authorization request. This list if used when looking through cached tokens to see if we would like to use any of the existing.\n* `scopes.request`: Control what scopes are requested in the authorization request. When none of the cached tokens will be used, and a new one will be request, the `scopes.request` list will be included in the authorization request.\n* `default_lifetime` : Seconds with default lifetime of an access token. If set to `false`, it means permanent. Default is 3600. This only matters if expires_in was not sent from the server, which should ALWAYS be the case.\n* `permanent_scope`: A scope that indicates that the lifetime of the access token is infinite. (not well-tested.)\n* `response_type`: Default response_type for all authorization requests. Default: `token`. Can be overriden to in example use OpenID Connect\n* `debug`: Default set to `false`. Set this to `true` to enable debug logging to console.\n* `request`: Optional additional request paramters added to the request. Useful for adding all the available OpenID Connect options\n\n\n### Catching the response when the user is returning\n\n\nOn the page (usually the same) that the user is sent back to after authorization, typically the `redirect_uri` endpoint, you would need to call the `callback`-function on JSO to tell it to check for response parameters:\n\n```javascript\nclient.callback()\n```\nBe aware to run the `callback()` function early, and before you *router* and before you start using the jso object to fetch data.\n\n\n\n### Getting the token\n\nTo get an token, use the `getToken` function:\n\n```javascript\nclient.getToken(opts)\n    .then((token) =\u003e {\n    \tconsole.log(\"I got the token: \", token)\n    })\n```\n\nYou may also ensure that a token is available early in your application, to force all user interaction and redirection to happen before your application is fully loaded. To do that make a call to getToken, and wait for the callback before you continue.\n\nREMEMBER to ALWAYS call the callback() function to process the response from the OAuth server, before you use getToken(), if not you will end up in an redirect_loop\n\n\nOptions to `getToken(opts)`\n\n* `allowredir`: Throw an exception if getToken would imply redirecting the user. Typically you would like to use checkToken() instead of using this.\n* `response_type`: Override for this specific request.\n* `scopes.require`: Override for this specific request.\n* `scopes.request`: Override for this specific request.\n\n\nAs an alternative to getToken(), you can check if the token is available with `checkToken()`.\n\n```javascript\nlet token = client.getToken(opts)\nif (token !== null) {\n\tconsole.log(\"I got the token: \", token)\n}\n```\n\nOptions to `checkToken(opts)`\n\n* `scopes.require`: Override for this specific request.\n\n### Logout\n\nYou may wipe all stored tokens, in order to simulate a *logout* experience:\n\n```javascript\nclient.wipeTokens()\n```\n\n\n### Fetching data from a OAuth protected endpoint\n\nJSO provides a simple wrapper around the [javascript Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).\n\nhttps://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\n\n\n```javascript\n\n// Initialization\nlet config = {...}\nlet client = new JSO(config)\nclient.callback()\n\n// When your application wants to access the protected data\nlet f = new Fetcher(client)\nlet url = 'https://some-api.httpjs.net/rest/me'\nf.fetch(url, {})\n\t.then((data) =\u003e {\n\t\treturn data.json()\n\t})\n\t.then((data) =\u003e {\n\t\tconsole.log(\"I got protected json data from the API\", data)\n\t})\n\t.catch((err) =\u003e {\n\t\tconsole.error(\"Error from fetcher\", err)\n\t})\n```\n\nIf you would like to ensure that the required access token is obtained earlier than when you would like to access data, you may use `getToken()` for that, and you do not need to read or process the response.\n\n```javascript\n// Making sure the token is obtained.\n// Will redirect the user for authentication if token is not available.\nclient.getToken({\n\tscopes: {\n\t\trequest: [\"profile\", \"restdata\", \"longterm\", \"email\"]\n\t\trequire: [\"profile\", \"restdata\", \"longterm\"]\n\t}\n})\n```\n\n\nThe `FetcherJQuery` is an alternative interface that uses `jQuery.ajax()` instead of `fetch()`. Consider the `FetcherJQuery` *beta*.\n\nNotice that this class takes the jQuery object as a second argument to the constructor. The fetch options argument is provided as options to `jQuery.ajax()`.\n\nThe `fetch()` function returns a Promise that resolves the response data.\n\n```javascript\n\n// Initialization\nlet f = new FetcherJQuery(client, $)\nlet url = 'https://some-api.httpjs.net/rest/me'\nf.fetch(url, {})\n\t.then((data) =\u003e {\n\t\tconsole.log(\"I got protected json data from the API\", data)\n\t})\n\t.catch((err) =\u003e {\n\t\tconsole.error(\"Error from fetcher\", err)\n\t})\n```\n\n\n## OAuth 2.0 Authorization Code flow\n\nIn the config include these parameters:\n\n```\n\tresponse_type: 'code',\n\tclient_secret: \"xxxxx-xxxx-xxx-xxx\",\n\ttoken: \"https://auth.dataporten.no/oauth/token\",\n```\n\nAlso be aware that the implementation of this flow uses `fetch`, to support older browser you would need to polyfill that.\n\n\n\n\n\n## Sending passive OpenID Connect authentication requests using hidden iFrames (Advanced)\n\nIf your OpenID Connect provider support passive requests and the enduser is already authenticated with single sign-on, you may obtain an authenticated state using a hidden iframe without redirecting the user at all.\n\nFirst, you will need a separate redirect page, as the provided `example/passiveCallback.html`.\n\n```javascript\nlet opts = {\n\tscopes: {\n\t\trequest: ['email','longterm', 'openid', 'profile']\n\t},\n\trequest: {\n\t\tprompt: \"none\"\n\t},\n\tresponse_type: 'id_token token',\n\tredirect_uri: \"http://localhost:8001/passiveCallback.html\"\n}\nclient.setLoader(IFramePassive)\nclient.getToken(opts)\n\t.then((token) =\u003e {\n\t\tconsole.log(\"I got the token: \", token)\n\t})\n\t.catch((err) =\u003e {\n\t\tconsole.error(\"Error from passive loader\", err)\n\t})\n```\n\n\n## Making authentication of end user in a popup, avoiding interruption of the state of your web application (Advanced)\n\nIf you would like to redirect the end user to login without loosing the state in your web app, you may use a popup window. This\n\nFirst, you will need a separate redirect page, as the provided `example/popupCallback.html`.\n\n```javascript\nfunction authorizePopup() {\n\tlet opts = {\n\t\tredirect_uri: \"http://localhost:8001/popupCallback.html\"\n\t}\n\tclient.setLoader(Popup)\n\tclient.getToken(opts)\n\t\t.then((token) =\u003e {\n\t\t\tconsole.log(\"I got the token: \", token)\n\t\t})\n\t\t.catch((err) =\u003e {\n\t\t\tconsole.error(\"Error from passive loader\", err)\n\t\t})\n}\n$(\"#btnAuthenticate\").on('click', (e) =\u003e {\n\te.preventDefault()\n\tauthorizePopup()\n})\n```\n\n## Implementing a custom loader for use with in-app browser (Advanced)\n\nLook at the `src/Loaders/*.js` files to see how loaders are implemented, and create a custom loader for your use case.\n\nContributions of loaders for Cordova in-app browser and similar are welcome.\n\nThen use the `client.setLoader(Loader)` to use the custom loader. Out of the box, JSO comes with:\n\n* HTTPRedirect - default usage\n* Popup\n* IFramePassive\n\n\n\n## Using the examples\n\n```bash\ncd examples\npython -m SimpleHTTPServer 8990\n```\n\nThen visit http://localhost:8990/\n\n\n## Licence\n\n\nUNINETT holds the copyright of the JSO library. The software can be used free of charge for both non-commercial and commercial projects.\n\nThe software is dual-licenced with *The GNU Lesser General Public License, version 2.1 (LGPL-2.1)* and *version 3.0*; meaning that you can select which of these two versions depending on your needs.\n\n* \u003chttp://opensource.org/licenses/lgpl-2.1\u003e\n* \u003chttp://opensource.org/licenses/LGPL-3.0\u003e\n\n\n\n\n\u003c!--\n\n## Browser support\n\nVersion 3 of JSO makes use of ES6 Promises, which is not that well supported across browsers. The final release builds will include a polycfill that works with all browsers. More on that later...\n\nJSO uses localStorage for caching tokens. localStorage is supported in Firefox 3.5+, Safari 4+, IE8+, and Chrome. For better compatibility use the localstorage library that is included in the example.\n\nJSO uses JSON serialization functions (stringify and parse). These are supported in Firefox 3.5, Internet Explorer 8.0 and Chrome 3. For better compatibility use the JSON2.js library.\n\n--\u003e\n\n## Library size\n\n* 4.0.0:     12577 bytes\n* 4.0.0-rc6: 12582 bytes\n* 4.0.0-rc4: 12612 bytes\n\n\n## More from Uninett\n\nSee also our javascript API mock-up tool \u003chttps://httpjs.net\u003e, and our OAuth play tool \u003chttps://play.oauth.no\u003e.\n\n* [Follow Andreas Åkre Solberg on twitter](https://twitter.com/erlang)\n* [Read more about UNINETT](http://uninett.no)\n* Contact address: \u003cmailto:andreas.solberg@uninett.no\u003e\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandreassolberg%2Fjso","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandreassolberg%2Fjso","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandreassolberg%2Fjso/lists"}