├── .eslintignore ├── .eslintrc ├── .github ├── ISSUE_TEMPLATE │ ├── Bug_report.md │ ├── Feature_request.md │ ├── Question.md │ └── config.yml ├── PULL_REQUEST_TEMPLATE.md └── stale.yml ├── .gitignore ├── .jshintrc ├── .npmignore ├── .travis.yml ├── CHANGES.md ├── CODEOWNERS ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── NOTICE ├── README.md ├── common └── models │ ├── oauth-authorization-code.json │ ├── oauth-client-application.json │ ├── oauth-permission.json │ ├── oauth-scope-mapping.json │ ├── oauth-scope.json │ └── oauth-token.json ├── intl ├── cs │ └── messages.json ├── de │ └── messages.json ├── en │ └── messages.json ├── es │ └── messages.json ├── fr │ └── messages.json ├── it │ └── messages.json ├── ja │ └── messages.json ├── ko │ └── messages.json ├── nl │ └── messages.json ├── pl │ └── messages.json ├── pt │ └── messages.json ├── ru │ └── messages.json ├── tr │ └── messages.json ├── zh-Hans │ └── messages.json └── zh-Hant │ └── messages.json ├── lib ├── errors │ ├── authorizationerror.js │ ├── badrequesterror.js │ ├── forbiddenerror.js │ ├── oauth2error.js │ └── tokenerror.js ├── exchange │ ├── authorizationCode.js │ ├── clientCredentials.js │ ├── jwt.js │ ├── password.js │ └── refreshToken.js ├── grant │ ├── code.js │ └── token.js ├── index.js ├── mac-token.js ├── middleware │ ├── authorization.js │ ├── decision.js │ ├── errorHandler.js │ ├── revoke.js │ ├── token.js │ └── transactionLoader.js ├── models │ ├── index.js │ └── oauth2-models.js ├── oauth2-helper.js ├── oauth2-loopback.js ├── oauth2orize.js ├── resource-server.js ├── scope.js ├── server.js ├── strategy │ ├── jwt-bearer │ │ ├── index.js │ │ └── strategy.js │ └── mac │ │ ├── index.js │ │ └── strategy.js ├── unorderedlist.js └── utils.js ├── loopback-oauth2.png ├── package.json ├── support └── mk │ ├── coveralls.mk │ ├── istanbul.mk │ ├── jshint.mk │ ├── mocha.mk │ ├── node.mk │ ├── notes.mk │ └── testling.mk └── test ├── bootstrap └── node.js ├── errors ├── authorizationerror.test.js ├── badrequesterror.test.js ├── forbiddenerror.test.js └── tokenerror.test.js ├── exchange ├── authorizationCode.test.js ├── clientCredentials.test.js ├── password.test.js └── refreshToken.test.js ├── grant ├── code-test.js ├── code.test.js ├── token-test.js └── token.test.js ├── middleware ├── authorization.immediate.test.js ├── authorization.test.js ├── decision.test.js ├── errorHandler.test.js ├── token.test.js └── transactionLoader.test.js ├── package.test.js ├── passport-http-bearer ├── index-test.js └── strategy-test.js ├── server.exchange.test.js ├── server.grant.test.js ├── server.request.test.js ├── server.response.test.js ├── server.serialization.test.js ├── server.test.js └── unorderedlist.test.js /.eslintignore: -------------------------------------------------------------------------------- 1 | /lib/errors/** 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "loopback", 3 | "rules": { 4 | "max-len": ["error", 120, 4, { 5 | "ignoreComments": true, 6 | "ignoreUrls": true, 7 | "ignorePattern": "^\\s*var\\s.+=\\s*(require\\s*\\()|(/)" 8 | }], 9 | "camelcase": 0, 10 | "one-var": "off", 11 | "no-unused-expressions": "off" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | labels: bug 5 | 6 | --- 7 | 8 | 18 | 19 | ## Steps to reproduce 20 | 21 | 22 | 23 | ## Current Behavior 24 | 25 | 26 | 27 | ## Expected Behavior 28 | 29 | 30 | 31 | ## Link to reproduction sandbox 32 | 33 | 37 | 38 | ## Additional information 39 | 40 | 45 | 46 | ## Related Issues 47 | 48 | 49 | 50 | _See [Reporting Issues](http://loopback.io/doc/en/contrib/Reporting-issues.html) for more tips on writing good issues_ 51 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | labels: feature 5 | 6 | --- 7 | 8 | ## Suggestion 9 | 10 | 11 | 12 | ## Use Cases 13 | 14 | 18 | 19 | ## Examples 20 | 21 | 22 | 23 | ## Acceptance criteria 24 | 25 | TBD - will be filled by the team. 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: The issue tracker is not for questions. Please use Stack Overflow or other resources for help. 4 | labels: question 5 | 6 | --- 7 | 8 | 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Report a security vulnerability 4 | url: https://loopback.io/doc/en/contrib/Reporting-issues.html#security-issues 5 | about: Do not report security vulnerabilities using GitHub issues. Please send an email to `reachsl@us.ibm.com` instead. 6 | - name: Get help on StackOverflow 7 | url: https://stackoverflow.com/tags/loopbackjs 8 | about: Please ask and answer questions on StackOverflow. 9 | - name: Join our mailing list 10 | url: https://groups.google.com/forum/#!forum/loopbackjs 11 | about: You can also post your question to our mailing list. 12 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | ## Checklist 12 | 13 | 👉 [Read and sign the CLA (Contributor License Agreement)](https://cla.strongloop.com/agreements/strongloop/loopback-component-oauth2) 👈 14 | 15 | - [ ] `npm test` passes on your machine 16 | - [ ] New tests added or existing tests modified to cover all changes 17 | - [ ] Code conforms with the [style guide](https://loopback.io/doc/en/contrib/style-guide-es6.html) 18 | - [ ] Commit messages are following our [guidelines](https://loopback.io/doc/en/contrib/git-commit-messages.html) 19 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 14 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | - critical 10 | - p1 11 | - major 12 | # Label to use when marking an issue as stale 13 | staleLabel: stale 14 | # Comment to post when marking an issue as stale. Set to `false` to disable 15 | markComment: > 16 | This issue has been automatically marked as stale because it has not had 17 | recent activity. It will be closed if no further activity occurs. Thank you 18 | for your contributions. 19 | # Comment to post when closing a stale issue. Set to `false` to disable 20 | closeComment: > 21 | This issue has been closed due to continued inactivity. Thank you for your understanding. 22 | If you believe this to be in error, please contact one of the code owners, 23 | listed in the `CODEOWNERS` file at the top-level of this repository. 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | reports/ 3 | 4 | # Node.js 5 | node_modules/ 6 | npm-debug.log 7 | 8 | # Mac OS X 9 | .DS_Store 10 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "bitwise": true, 4 | "camelcase": true, 5 | "curly": true, 6 | "forin": true, 7 | "immed": true, 8 | "latedef": true, 9 | "newcap": true, 10 | "noarg": true, 11 | "noempty": true, 12 | "nonew": true, 13 | "quotmark": "single", 14 | "undef": true, 15 | "unused": true, 16 | "trailing": true, 17 | "laxcomma": true 18 | } 19 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | README.md 3 | build/ 4 | docs/ 5 | examples/ 6 | reports/ 7 | support/ 8 | test/ 9 | 10 | # Node.js 11 | .npmignore 12 | node_modules/ 13 | npm-debug.log 14 | 15 | # Mac OS X 16 | .DS_Store 17 | 18 | # Git 19 | .git* 20 | 21 | # Utilities 22 | .jshintrc 23 | .travis.yml 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: "node_js" 2 | node_js: 3 | - "6" 4 | - "8" 5 | - "10" 6 | 7 | before_install: 8 | - "npm install istanbul -g" 9 | - "npm install coveralls -g" 10 | 11 | script: "make ci-travis" 12 | 13 | after_success: 14 | - "make submit-cov-to-coveralls" 15 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Lines starting with '#' are comments. 2 | # Each line is a file pattern followed by one or more owners, 3 | # the last matching pattern has the most precendence. 4 | 5 | # Core team members from IBM and community contributors 6 | * @kjdelisle @jannyHou @loay @b-admike @ssh24 @virkt25 @dhmlau @ebarault 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) IBM Corp. 2012,2017. All Rights Reserved. 2 | Node module: loopback-component-oauth2 3 | This project is licensed under the MIT License, full text below. 4 | 5 | -------- 6 | 7 | MIT license 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in 17 | all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SOURCES ?= lib/*.js lib/**/*.js 2 | TESTS ?= test/*.test.js test/**/*.test.js 3 | 4 | test: test-mocha 5 | test-cov: test-istanbul-mocha 6 | view-cov: view-istanbul-report 7 | lint: lint-jshint 8 | lint-tests: lint-tests-jshint 9 | 10 | 11 | # ============================================================================== 12 | # Node.js 13 | # ============================================================================== 14 | include support/mk/node.mk 15 | include support/mk/mocha.mk 16 | include support/mk/istanbul.mk 17 | 18 | # ============================================================================== 19 | # Analysis 20 | # ============================================================================== 21 | include support/mk/notes.mk 22 | include support/mk/jshint.mk 23 | 24 | # ============================================================================== 25 | # Reports 26 | # ============================================================================== 27 | include support/mk/coveralls.mk 28 | 29 | # ============================================================================== 30 | # Continuous Integration 31 | # ============================================================================== 32 | submit-cov-to-coveralls: submit-istanbul-lcov-to-coveralls 33 | 34 | # Travis CI 35 | ci-travis: test test-cov 36 | 37 | # ============================================================================== 38 | # Clean 39 | # ============================================================================== 40 | clean: 41 | rm -rf build 42 | rm -rf reports 43 | 44 | clobber: clean clobber-node 45 | 46 | 47 | .PHONY: test test-cov view-cov lint lint-tests submit-cov-to-coveralls ci-travis clean clobber 48 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This product includes software developed at https://github.com/jaredhanson/oauth2orize under the following MIT license. 2 | 3 | Copyright (c) 2012-2013 Jared Hanson 4 | 5 | The MIT License (MIT) 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # loopback-component-oauth2 2 | 3 | The LoopBack oAuth 2.0 component provides full integration between [OAuth 2.0](http://tools.ietf.org/html/rfc6749) 4 | and [LoopBack](http://loopback.io). It enables LoopBack applications to function 5 | as an oAuth 2.0 provider to authenticate and authorize client applications and/or 6 | resource owners (i.e. users) to access protected API endpoints. 7 | 8 | The oAuth 2.0 protocol implementation is based on [oauth2orize](https://github.com/jaredhanson/oauth2orize) 9 | and [passport](http://passportjs.org/). 10 | 11 | See [LoopBack Documentation - OAuth 2.0 Component](http://loopback.io/doc/en/lb2/OAuth-2.0.html) for more information. 12 | 13 | ## Install 14 | 15 | Install the component as usual: 16 | 17 | ``` 18 | $ npm install loopback-component-oauth2 19 | ``` 20 | 21 | ## Use 22 | 23 | Use in an application as follows: 24 | 25 | ```js 26 | var oauth2 = require('loopback-component-oauth2'); 27 | 28 | var options = { 29 | dataSource: app.dataSources.db, // Data source for oAuth2 metadata persistence 30 | loginPage: '/login', // The login page url 31 | loginPath: '/login' // The login form processing url 32 | }; 33 | 34 | oauth2.oAuth2Provider( 35 | app, // The app instance 36 | options // The options 37 | ); 38 | ``` 39 | 40 | The app instance will be used to set up middleware and routes. The data source 41 | provides persistence for the oAuth 2.0 metadata models. 42 | 43 | For more information, see [OAuth 2.0](http://loopback.io/doc/en/lb2/OAuth-2.0.html) LoopBack component official documentation. 44 | 45 | ## Example 46 | 47 | This [example](https://github.com/strongloop/strong-gateway) demonstrates 48 | how to implement an OAuth service provider, complete with protected API access. 49 | -------------------------------------------------------------------------------- /common/models/oauth-authorization-code.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OAuthAuthorizationCode", 3 | "base": "PersistedModel", 4 | "properties": { 5 | "id": { 6 | "type": "string", 7 | "id": true, 8 | "length": 300, 9 | "generated": false 10 | }, 11 | "appId": { 12 | "type": "string", 13 | "length": 128, 14 | "index": true 15 | }, 16 | "userId": { 17 | "type": "string", 18 | "index": true 19 | }, 20 | "issuedAt": { 21 | "type": "date", 22 | "index": true 23 | }, 24 | "expiresIn": "number", 25 | "expiredAt": { 26 | "type": "date", 27 | "index": true 28 | }, 29 | "scopes": [ "string" ], 30 | "parameters": [ 31 | { 32 | "name": "string", 33 | "value": "string" 34 | } 35 | ], 36 | "used": "boolean", 37 | "redirectURI": "string", 38 | "hash": "string" 39 | }, 40 | "relations": { 41 | "application": { 42 | "type": "belongsTo", 43 | "model": "OAuthClientApplication", 44 | "foreignKey": "appId" 45 | }, 46 | "user": { 47 | "type": "belongsTo", 48 | "model": "User", 49 | "foreignKey": "userId" 50 | } 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /common/models/oauth-client-application.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OAuthClientApplication", 3 | "base": "Application", 4 | "properties": { 5 | "id": { 6 | "type": "string", 7 | "id": true, 8 | "generated": false, 9 | "length": 128 10 | }, 11 | "clientType": { 12 | "type": "string", 13 | "enum": ["public", "confidential"] 14 | }, 15 | "redirectURIs": [ "string" ], 16 | "tokenEndpointAuthMethod": { 17 | "type": "string", 18 | "enum": ["none", "client_secret_post", "client_secret_basic"] 19 | }, 20 | "grantTypes": [ 21 | { 22 | "type": "string", 23 | "enum": ["authorization_code", "implicit", "client_credentials", 24 | "password", "urn:ietf:params:oauth:grant-type:jwt-bearer", 25 | "urn:ietf:params:oauth:grant-type:saml2-bearer"] 26 | } 27 | ], 28 | "responseTypes": [ 29 | { 30 | "type": "string", 31 | "enum": ["code", "token"] 32 | } 33 | ], 34 | "tokenType": { 35 | "type": "string", 36 | "enum": ["bearer", "jwt", "mac"] 37 | }, 38 | "clientSecret": "string", 39 | "clientName": "string", 40 | "clientURI": "string", 41 | "logoURI": "string", 42 | "scopes": ["string"], 43 | "contacts": ["string"], 44 | "tosURI": "string", 45 | "policyURI": "string", 46 | "jwksURI": "string", 47 | "jwks": { 48 | "type": "string", 49 | "mysql": { 50 | "dataLength": 4096, 51 | "dataType": "TEXT" 52 | } 53 | }, 54 | "softwareId": "string", 55 | "softwareVersion": "string", 56 | 57 | "callbackUrls": null, 58 | "permissions": null, 59 | "authenticationEnabled": null, 60 | "anonymousAllowed": null, 61 | "authenticationSchemes": null, 62 | "icon": null, 63 | "url": null 64 | }, 65 | "comments": "https://tools.ietf.org/html/draft-ietf-oauth-dyn-reg-24" 66 | } -------------------------------------------------------------------------------- /common/models/oauth-permission.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OAuthPermission", 3 | "base": "PersistedModel", 4 | "properties": { 5 | "appId": { 6 | "type": "string", 7 | "length": 128, 8 | "index": true 9 | }, 10 | "userId": { 11 | "type": "string", 12 | "index": true 13 | }, 14 | "issuedAt": { 15 | "type": "date", 16 | "index": true 17 | }, 18 | "expiresIn": "number", 19 | "expiredAt": { 20 | "type": "date", 21 | "index": true 22 | }, 23 | "scopes": [ "string" ] 24 | }, 25 | "relations": { 26 | "application": { 27 | "type": "belongsTo", 28 | "model": "OAuthClientApplication", 29 | "foreignKey": "appId" 30 | }, 31 | "user": { 32 | "type": "belongsTo", 33 | "model": "User", 34 | "foreignKey": "userId" 35 | } 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /common/models/oauth-scope-mapping.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OAuthScopeMapping", 3 | "properties": { 4 | "scope": { 5 | "type": "string", 6 | "length": 255, 7 | "index": true, 8 | "description": "The scope name" 9 | }, 10 | "route": { 11 | "type": "string", 12 | "description": "The route as [verb] /api/users" 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /common/models/oauth-scope.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OAuthScope", 3 | "properties": { 4 | "scope": { 5 | "type": "string", 6 | "id": true, 7 | "generated": false 8 | }, 9 | "description": "string", 10 | "iconURL": "string", 11 | "ttl": "number" 12 | } 13 | } -------------------------------------------------------------------------------- /common/models/oauth-token.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OAuthAccessToken", 3 | "base": "PersistedModel", 4 | "properties": { 5 | "id": { 6 | "type": "string", 7 | "id": true, 8 | "length": 300, 9 | "generated": false 10 | }, 11 | "appId": { 12 | "type": "string", 13 | "length": 128, 14 | "index": true 15 | }, 16 | "userId": { 17 | "type": "string", 18 | "index": true 19 | }, 20 | "issuedAt": { 21 | "type": "date", 22 | "index": true 23 | }, 24 | "expiresIn": "number", 25 | "expiredAt": { 26 | "type": "date", 27 | "index": true 28 | }, 29 | "scopes": [ "string" ], 30 | "parameters": [ 31 | { 32 | "name": "string", 33 | "value": "string" 34 | } 35 | ], 36 | "authorizationCode": { 37 | "type": "string", 38 | "length": 300, 39 | "index": true 40 | }, 41 | "refreshToken": { 42 | "type": "string", 43 | "length": 300, 44 | "index": true 45 | }, 46 | "tokenType": { 47 | "type": "string", 48 | "enum": [ "Bearer", "MAC" ] 49 | }, 50 | "hash": "string" 51 | }, 52 | "relations": { 53 | "application": { 54 | "type": "belongsTo", 55 | "model": "OAuthClientApplication", 56 | "foreignKey": "appId" 57 | }, 58 | "user": { 59 | "type": "belongsTo", 60 | "model": "User", 61 | "foreignKey": "userId" 62 | } 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /intl/cs/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "06f6133efc10bf1f9a2c6b5161c66fba": "Tělo požadavku nebylo analyzováno. Použijte middleware {{bodyParser}}.", 3 | "083123c0a745a514ce06fa527c151a46": "Middleware {{oauth2orize.authorization}} vyžaduje argument {{server}}", 4 | "092f3dd9c9bde61eed97f67459b46a7e": "Nepodporovaný typ odezvy: {0}", 5 | "102a3213ff01fc1b03faa5cbe720e6c0": "Neplatný autorizační kód", 6 | "10b283f781f47e879e25e3b3b84f85e3": "Oprávnění odepřeno uživatelem {0}", 7 | "12df3715215d39fdb1c5c19775091f31": "{{OAuth2orize}} vyžaduje syntaktickou analýzu těla. Zapomněli jste {{app.use(express.bodyParser())}}?", 8 | "14b06036ad206e2b038840c24e677b4d": "{{OAuth2orize}} vyžaduje podporu transakcí. Zapomněli jste {{oauth2orize.transactionLoader(...)}}?", 9 | "19d7beb3c393b20162c2c43135b4f1c0": "Autorizační kód má vypršenou platnost", 10 | "1e1b2073df0a8963670e9ed1e181dfe8": "Neplatný {{JWT}}: {0}", 11 | "24ff616d05fe6b8dca8859d9dafa729e": "Neplatný klient", 12 | "2caa676b18561101c92e69d70820b1bf": "{{OAuth2orize}} vyžaduje podporu {{session}}. Zapomněli jste {{app.use(express.session(...))}}?", 13 | "37086a106da98d5322d134d7905d1817": "Chybí povinný parametr: {{code}}", 14 | "373b2ad70311b6537ad42719088da022": "Nezdařilo se deserializovat klienta. Registrovat deserializační funkci pomocí {{deserializeClient()}}.", 15 | "3bffb3bbef4312d6bcbabd3240e79ef2": "Udělení {{oauth2orize.code}} vyžaduje zpětné volání {{issue}}", 16 | "3cfcae051965e0da5f704a334e1e884c": "Neshody ID klienta", 17 | "43a5b5bf0c7dd0bf5fec2601fe347245": "Neplatný požadavek: {{redirect_uri}} chybí", 18 | "4428b355c8ba3e248b8fc0857e2181a0": "Nepodporovaný typ udělení: {0}", 19 | "452b7bd4aed1b69b7c20fb701377c4eb": "Neautorizovaný {{redirectURI}}: {0}", 20 | "47db77dd8ab3aa3c3ec1e6c955c0cc01": "Chybí povinný parametr: {{username}}", 21 | "53c21d3a92686e2956d527d097e1e1b9": "Přístupový token má neplatné {{user id}}: {0}", 22 | "54d8df1f46d3358dd33ba274a537b519": "Nepodporovaný typ tokenu: {0}", 23 | "5b853ac61fab20ec62d53e183e067ec3": "Nezdařila se serializace klienta. Zaregistrujte serializační funkci pomocí {{serializeClient()}}.", 24 | "5bc4d117f87ba20efb8cdd4c988ed46d": "Middleware {{oauth2orize.transactionLoader}} vyžaduje argument {{server}}", 25 | "6d3b5c2b2c7c20cd8907a0b090f0e89c": "Neplatný aktualizační token", 26 | "6e0122e493bd949f408c1421fc757b95": "Nelze vydat přesměrování pro transakci {{OAuth 2.0}}", 27 | "7175ea69be895be338ca9f9168268dab": "Middleware {{oauth2orize.decision}} vyžaduje argument {{server}}", 28 | "740f3fb2bd1358d65943e735224d23e5": "Chybí povinný parametr: {{refresh_token}}", 29 | "76d075ea0325d32667fad67c446e469b": "neplatný {{JWT}}", 30 | "8000aa2c64d9c95c406053764fc33f64": "Neoprávněný klient", 31 | "83459aaa8e2d81c7fad2b899ad0cbf57": "Komponenta {{OAuth2}} nebyla nakonfigurována pro tuto aplikaci.", 32 | "839544ec984d6290cd45669efdd39699": "Přesměrovat neshody {{uri}}", 33 | "8782860f8d60f2bdb6f67d623dd7e51f": "Middleware {{oauth2orize.authorization}} vyžaduje funkci {{validate}}", 34 | "9508d060bc6fd6e25cb4d0c00ea0480d": "Nedostatečný rozsah", 35 | "a198c4335c42739230d7d8afacdc109d": "Middleware výměny {{OAuth 2.0 jwtBearer}} vyžaduje funkci {{issue}}.", 36 | "a23d7ec09a60c8bbd119d8287d8b5805": "Middleware {{oauth2orize.revoke}} vyžaduje funkci {{revokeToken}}", 37 | "a2f3ad97b7b05618b6722b8f07e9f805": "Strategie typu bearer {{OAuth 2.0 JWT}} vyžaduje ověření zpětného volání", 38 | "a7b39a5a13fdba4772a83e07cb864156": "Nelze načíst transakce {{OAuth 2.0}} z relace", 39 | "a82c6b0f0db10b6e198e99068e765570": "Strategie typu bearer {{OAuth 2.0 JWT}} vyžaduje volbu příjemce", 40 | "aaee2c79ab90ccc63b9d46795e19620a": "Výměna {{oauth2orize.clientCredentials}} vyžaduje vydání zpětného volání", 41 | "ae02475e560f64afdcf6d02bc80dcb0e": "Neplatná pověření klienta", 42 | "b1af8f34c3d25bd59189205046665bfd": "Chybí povinný parametr: {0}", 43 | "b1eb21b6d32dde679f9b4bf0b2e0939d": "{{MACStrategy}} vyžaduje ověření zpětného volání", 44 | "bac74f7415259e303903cfc8a7bcc4df": "Middleware {{oauth2orize.token}} vyžaduje argument {{server}}", 45 | "bcb1c003530e6fb715ad605ea7fe83d9": "Udělení {{oauth2orize.token}} vyžaduje zpětné volání {{issue}}", 46 | "cbd12265f4ab78b30a0977e37aefcf37": "Chybí povinný parametr: {{password}}", 47 | "cdee717bf439af4c84eabb54b82c13af": "Výměna {{oauth2orize.authorizationCode}} vyžaduje vydání zpětného volání", 48 | "d36b1a9f8719a56a091ed6c89d3cd1fa": "Požadavek byl zamítnut autorizačním serverem", 49 | "d3dd8b2220bba70a6e7e44af24a4157c": "Chybí povinný parametr: {{token}}", 50 | "d837f7c0309bf4816cbbb22b57473733": "Výměna {{oauth2orize.password}} vyžaduje zpětné volání {{issue}}", 51 | "d83b55a5dfd3e16ca22699e39b072f3f": "Přístupový token má neplatné {{app id}}: {0}", 52 | "db8b02ad229f45cbb12e0d9845b09eb2": "Strategie typu bearer {{OAuth 2.0 JWT}} vyžaduje klíčování zpětného volání", 53 | "e173a3cecca19bcbf528408adc001750": "Neautorizovaný typ odezvy: {0}", 54 | "e82c91e82424949d4390135e5e8adf1c": "Neplatný token {{MAC}}", 55 | "eb30f051fcf0e7338bf4d8489f583378": "Neautorizovaný {{scope}}: {0}", 56 | "ec30fea412580b611d7a274ee1163e5c": "Chybí povinný parametr: {{response_type}}", 57 | "ec9ddf242c3da3b5cf44def6398706ec": "Výměna {{oauth2orize.refreshToken}} vyžaduje zpětné volání {{issue}}", 58 | "ed5c8e0055b1cae433e4c393ae04d555": "Neplatné položky: {0}", 59 | "f06abf2e08aba65a62f4486bc2418413": "Middleware {{oauth2orize.revoke}} vyžaduje argument {{server}}", 60 | "f24b75ecdc45edb84b0c9fec3b6f1e5b": "Nelze načíst transakci {{OAuth 2.0}}: {0}", 61 | "f483b2bebd08d285c7009c6812f5ba24": "Platnost přístupového tokenu vypršela", 62 | "f50708df489d7811db692c0b601483f8": "Chybí povinný parametr: {{client_id}}", 63 | "fa925eb4771bd2897f14b1de78ca0ed2": "Neplatný předmět: {0}", 64 | "fcdd5cf7956698312e899ddb708abbaf": "chybějící parametr deklarace", 65 | "fef19f407c562658e0132f1625ce968b": "Neautorizovaný typ udělení: {0}", 66 | "ff7883d90a5fe850e026885759165406": "Neplatná pověření vlastníka prostředku" 67 | } 68 | 69 | -------------------------------------------------------------------------------- /intl/de/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "06f6133efc10bf1f9a2c6b5161c66fba": "Anforderungshauptteil nicht geparst. Verwenden Sie {{bodyParser}}-Middleware.", 3 | "083123c0a745a514ce06fa527c151a46": "{{oauth2orize.authorization}}-Middleware erfordert ein {{server}}-Argument", 4 | "092f3dd9c9bde61eed97f67459b46a7e": "Nicht unterstützter Antworttyp: {0}", 5 | "102a3213ff01fc1b03faa5cbe720e6c0": "Ungültiger Berechtigungscode", 6 | "10b283f781f47e879e25e3b3b84f85e3": "Berechtigung verweigert von {0}", 7 | "12df3715215d39fdb1c5c19775091f31": "{{OAuth2orize}} erfordert Hauptteil-Parsing. Haben Sie {{app.use(express.bodyParser())}} vergessen?", 8 | "14b06036ad206e2b038840c24e677b4d": "{{OAuth2orize}} erfordert Transaktionsunterstützung. Haben Sie {{oauth2orize.transactionLoader(...)}} vergessen?", 9 | "19d7beb3c393b20162c2c43135b4f1c0": "Berechtigungscode ist abgelaufen", 10 | "1e1b2073df0a8963670e9ed1e181dfe8": "Ungültiges {{JWT}}: {0}", 11 | "24ff616d05fe6b8dca8859d9dafa729e": "Ungültiger Client", 12 | "2caa676b18561101c92e69d70820b1bf": "{{OAuth2orize}} erfordert Unterstützung für {{session}}. Haben Sie {{app.use(express.session(...))}} vergessen?", 13 | "37086a106da98d5322d134d7905d1817": "Erforderlicher Parameter fehlt: {{code}}", 14 | "373b2ad70311b6537ad42719088da022": "Client wurde nicht deserialisiert. Registrieren Sie die Deserialisierungsfunktion mit {{deserializeClient()}}.", 15 | "3bffb3bbef4312d6bcbabd3240e79ef2": "Bewilligung von {{oauth2orize.code}} erfordert einen {{issue}}-Rückruf", 16 | "3cfcae051965e0da5f704a334e1e884c": "Fehlende Übereinstimmungen bei Client-ID", 17 | "43a5b5bf0c7dd0bf5fec2601fe347245": "Ungültige Anforderung: {{redirect_uri}} fehlt", 18 | "4428b355c8ba3e248b8fc0857e2181a0": "Nicht unterstützter Bewilligungstyp: {0}", 19 | "452b7bd4aed1b69b7c20fb701377c4eb": "Nicht autorisierter {{redirectURI}}: {0}", 20 | "47db77dd8ab3aa3c3ec1e6c955c0cc01": "Erforderlicher Parameter fehlt: {{username}}", 21 | "53c21d3a92686e2956d527d097e1e1b9": "Zugriffstoken hat eine ungültige {{user id}}: {0}", 22 | "54d8df1f46d3358dd33ba274a537b519": "Nicht unterstützter Tokentyp: {0}", 23 | "5b853ac61fab20ec62d53e183e067ec3": "Client wurde nicht serialisiert. Registrieren Sie die Serialisierungsfunktion mit {{serializeClient()}}.", 24 | "5bc4d117f87ba20efb8cdd4c988ed46d": "{{oauth2orize.transactionLoader}}-Middleware erfordert ein {{server}}-Argument", 25 | "6d3b5c2b2c7c20cd8907a0b090f0e89c": "Ungültiges Aktualisierungstoken", 26 | "6e0122e493bd949f408c1421fc757b95": "Es kann keine Umleitung für {{OAuth 2.0}}-Transaktion ausgegeben werden", 27 | "7175ea69be895be338ca9f9168268dab": "{{oauth2orize.decision}}-Middleware erfordert ein {{server}}-Argument", 28 | "740f3fb2bd1358d65943e735224d23e5": "Erforderlicher Parameter fehlt: {{refresh_token}}", 29 | "76d075ea0325d32667fad67c446e469b": "ungültiges {{JWT}}", 30 | "8000aa2c64d9c95c406053764fc33f64": "Nicht autorisierter Client", 31 | "83459aaa8e2d81c7fad2b899ad0cbf57": "Die {{OAuth2}}-Komponente wurde nicht für diese Anwendung konfiguriert.", 32 | "839544ec984d6290cd45669efdd39699": "Fehlende Übereinstimmungen bei Umleitungs-{{uri}}", 33 | "8782860f8d60f2bdb6f67d623dd7e51f": "{{oauth2orize.authorization}}-Middleware erfordert eine {{validate}}-Funktion", 34 | "9508d060bc6fd6e25cb4d0c00ea0480d": "Nicht ausreichender Bereich", 35 | "a198c4335c42739230d7d8afacdc109d": "{{OAuth 2.0 jwtBearer}}-Austausch-Middleware erfordert eine {{issue}}-Funktion.", 36 | "a23d7ec09a60c8bbd119d8287d8b5805": "{{oauth2orize.revoke}}-Middleware erfordert eine {{revokeToken}}-Funktion", 37 | "a2f3ad97b7b05618b6722b8f07e9f805": "{{OAuth 2.0 JWT}}-Trägerstrategie erfordert einen Bestätigungsrückruf", 38 | "a7b39a5a13fdba4772a83e07cb864156": "{{OAuth 2.0}}-Transaktionen können nicht aus Sitzung geladen werden", 39 | "a82c6b0f0db10b6e198e99068e765570": "{{OAuth 2.0 JWT}}-Trägerstrategie erfordert eine Zielgruppenoption", 40 | "aaee2c79ab90ccc63b9d46795e19620a": "Austausch von {{oauth2orize.clientCredentials}} erfordert einen Problemrückruf", 41 | "ae02475e560f64afdcf6d02bc80dcb0e": "Ungültige Berechtigungsnachweise", 42 | "b1af8f34c3d25bd59189205046665bfd": "Erforderlicher Parameter fehlt: {0}", 43 | "b1eb21b6d32dde679f9b4bf0b2e0939d": "{{MACStrategy}} erfordert einen Bestätigungsrückruf", 44 | "bac74f7415259e303903cfc8a7bcc4df": "{{oauth2orize.token}}-Middleware erfordert ein {{server}}-Argument", 45 | "bcb1c003530e6fb715ad605ea7fe83d9": "Bewilligung von {{oauth2orize.token}} erfordert einen {{issue}}-Rückruf", 46 | "cbd12265f4ab78b30a0977e37aefcf37": "Erforderlicher Parameter fehlt: {{password}}", 47 | "cdee717bf439af4c84eabb54b82c13af": "Austausch von {{oauth2orize.authorizationCode}} erfordert einen Problemrückruf", 48 | "d36b1a9f8719a56a091ed6c89d3cd1fa": "Anforderung vom Berechtigungsserver verweigert", 49 | "d3dd8b2220bba70a6e7e44af24a4157c": "Erforderlicher Parameter fehlt: {{token}}", 50 | "d837f7c0309bf4816cbbb22b57473733": "Austausch von {{oauth2orize.password}} erfordert einen {{issue}}-Rückruf", 51 | "d83b55a5dfd3e16ca22699e39b072f3f": "Zugriffstoken hat eine ungültige {{app id}}: {0}", 52 | "db8b02ad229f45cbb12e0d9845b09eb2": "{{OAuth 2.0 JWT}}-Trägerstrategie erfordert einen Texteingaberückruf", 53 | "e173a3cecca19bcbf528408adc001750": "Nicht autorisierter Antworttyp: {0}", 54 | "e82c91e82424949d4390135e5e8adf1c": "Ungültiges {{MAC}}-Token", 55 | "eb30f051fcf0e7338bf4d8489f583378": "Nicht autorisierter {{scope}}: {0}", 56 | "ec30fea412580b611d7a274ee1163e5c": "Erforderlicher Parameter fehlt: {{response_type}}", 57 | "ec9ddf242c3da3b5cf44def6398706ec": "Austausch von {{oauth2orize.refreshToken}} erfordert einen {{issue}}-Rückruf", 58 | "ed5c8e0055b1cae433e4c393ae04d555": "Ungültige Elemente: {0}", 59 | "f06abf2e08aba65a62f4486bc2418413": "{{oauth2orize.revoke}}-Middleware erfordert ein {{server}}-Argument", 60 | "f24b75ecdc45edb84b0c9fec3b6f1e5b": "{{OAuth 2.0}}-Transaktion kann nicht geladen werden: {0}", 61 | "f483b2bebd08d285c7009c6812f5ba24": "Zugriffstoken ist abgelaufen", 62 | "f50708df489d7811db692c0b601483f8": "Erforderlicher Parameter fehlt: {{client_id}}", 63 | "fa925eb4771bd2897f14b1de78ca0ed2": "Ungültiger Betreff: {0}", 64 | "fcdd5cf7956698312e899ddb708abbaf": "Assertionsparameter fehlt", 65 | "fef19f407c562658e0132f1625ce968b": "Nicht autorisierter Typ: {0}", 66 | "ff7883d90a5fe850e026885759165406": "ungültige Ressourceneigner-Berechtigungsnachweise" 67 | } 68 | 69 | -------------------------------------------------------------------------------- /intl/en/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "06f6133efc10bf1f9a2c6b5161c66fba": "Request body not parsed. Use {{bodyParser}} middleware.", 3 | "083123c0a745a514ce06fa527c151a46": "{{oauth2orize.authorization}} middleware requires a {{server}} argument", 4 | "092f3dd9c9bde61eed97f67459b46a7e": "Unsupported response type: {0}", 5 | "102a3213ff01fc1b03faa5cbe720e6c0": "Invalid authorization code", 6 | "10b283f781f47e879e25e3b3b84f85e3": "Permission denied by {0}", 7 | "12df3715215d39fdb1c5c19775091f31": "{{OAuth2orize}} requires body parsing. Did you forget {{app.use(express.bodyParser())}}?", 8 | "14b06036ad206e2b038840c24e677b4d": "{{OAuth2orize}} requires transaction support. Did you forget {{oauth2orize.transactionLoader(...)}}?", 9 | "19d7beb3c393b20162c2c43135b4f1c0": "Authorization code is expired", 10 | "1e1b2073df0a8963670e9ed1e181dfe8": "Invalid {{JWT}}: {0}", 11 | "24ff616d05fe6b8dca8859d9dafa729e": "Invalid client", 12 | "2caa676b18561101c92e69d70820b1bf": "{{OAuth2orize}} requires {{session}} support. Did you forget {{app.use(express.session(...))}}?", 13 | "37086a106da98d5322d134d7905d1817": "Missing required parameter: {{code}}", 14 | "373b2ad70311b6537ad42719088da022": "Failed to deserialize client. Register deserialization function using {{deserializeClient()}}.", 15 | "3bffb3bbef4312d6bcbabd3240e79ef2": "{{oauth2orize.code}} grant requires an {{issue}} callback", 16 | "3cfcae051965e0da5f704a334e1e884c": "Client id mismatches", 17 | "43a5b5bf0c7dd0bf5fec2601fe347245": "Invalid request: {{redirect_uri}} is missing", 18 | "4428b355c8ba3e248b8fc0857e2181a0": "Unsupported grant type: {0}", 19 | "452b7bd4aed1b69b7c20fb701377c4eb": "Unauthorized {{redirectURI}}: {0}", 20 | "47db77dd8ab3aa3c3ec1e6c955c0cc01": "Missing required parameter: {{username}}", 21 | "53c21d3a92686e2956d527d097e1e1b9": "Access token has invalid {{user id}}: {0}", 22 | "54d8df1f46d3358dd33ba274a537b519": "Unsupported token type: {0}", 23 | "5b853ac61fab20ec62d53e183e067ec3": "Failed to serialize client. Register serialization function using {{serializeClient()}}.", 24 | "5bc4d117f87ba20efb8cdd4c988ed46d": "{{oauth2orize.transactionLoader}} middleware requires a {{server}} argument", 25 | "6d3b5c2b2c7c20cd8907a0b090f0e89c": "Invalid refresh token", 26 | "6e0122e493bd949f408c1421fc757b95": "Unable to issue redirect for {{OAuth 2.0}} transaction", 27 | "7175ea69be895be338ca9f9168268dab": "{{oauth2orize.decision}} middleware requires a {{server}} argument", 28 | "740f3fb2bd1358d65943e735224d23e5": "Missing required parameter: {{refresh_token}}", 29 | "76d075ea0325d32667fad67c446e469b": "invalid {{JWT}}", 30 | "8000aa2c64d9c95c406053764fc33f64": "Unauthorized client", 31 | "83459aaa8e2d81c7fad2b899ad0cbf57": "The {{OAuth2}} component was not configured for this application.", 32 | "839544ec984d6290cd45669efdd39699": "Redirect {{uri}} mismatches", 33 | "8782860f8d60f2bdb6f67d623dd7e51f": "{{oauth2orize.authorization}} middleware requires a {{validate}} function", 34 | "9508d060bc6fd6e25cb4d0c00ea0480d": "Insufficient scope", 35 | "a198c4335c42739230d7d8afacdc109d": "{{OAuth 2.0 jwtBearer}} exchange middleware requires an {{issue}} function.", 36 | "a23d7ec09a60c8bbd119d8287d8b5805": "{{oauth2orize.revoke}} middleware requires a {{revokeToken}} function", 37 | "a2f3ad97b7b05618b6722b8f07e9f805": "{{OAuth 2.0 JWT}} bearer strategy requires a verify callback", 38 | "a7b39a5a13fdba4772a83e07cb864156": "Unable to load {{OAuth 2.0}} transactions from session", 39 | "a82c6b0f0db10b6e198e99068e765570": "{{OAuth 2.0 JWT}} bearer strategy requires an audience option", 40 | "aaee2c79ab90ccc63b9d46795e19620a": "{{oauth2orize.clientCredentials}} exchange requires an issue callback", 41 | "ae02475e560f64afdcf6d02bc80dcb0e": "Invalid client credentials", 42 | "b1af8f34c3d25bd59189205046665bfd": "Missing required parameter: {0}", 43 | "b1eb21b6d32dde679f9b4bf0b2e0939d": "{{MACStrategy}} requires a verify callback", 44 | "bac74f7415259e303903cfc8a7bcc4df": "{{oauth2orize.token}} middleware requires a {{server}} argument", 45 | "bcb1c003530e6fb715ad605ea7fe83d9": "{{oauth2orize.token}} grant requires an {{issue}} callback", 46 | "cbd12265f4ab78b30a0977e37aefcf37": "Missing required parameter: {{password}}", 47 | "cdee717bf439af4c84eabb54b82c13af": "{{oauth2orize.authorizationCode}} exchange requires an issue callback", 48 | "d36b1a9f8719a56a091ed6c89d3cd1fa": "Request denied by authorization server", 49 | "d3dd8b2220bba70a6e7e44af24a4157c": "Missing required parameter: {{token}}", 50 | "d837f7c0309bf4816cbbb22b57473733": "{{oauth2orize.password}} exchange requires an {{issue}} callback", 51 | "d83b55a5dfd3e16ca22699e39b072f3f": "Access token has invalid {{app id}}: {0}", 52 | "db8b02ad229f45cbb12e0d9845b09eb2": "{{OAuth 2.0 JWT}} bearer strategy requires a keying callback", 53 | "e173a3cecca19bcbf528408adc001750": "Unauthorized response type: {0}", 54 | "e82c91e82424949d4390135e5e8adf1c": "Invalid {{MAC}} token", 55 | "eb30f051fcf0e7338bf4d8489f583378": "Unauthorized {{scope}}: {0}", 56 | "ec30fea412580b611d7a274ee1163e5c": "Missing required parameter: {{response_type}}", 57 | "ec9ddf242c3da3b5cf44def6398706ec": "{{oauth2orize.refreshToken}} exchange requires an {{issue}} callback", 58 | "ed5c8e0055b1cae433e4c393ae04d555": "Invalid items: {0}", 59 | "f06abf2e08aba65a62f4486bc2418413": "{{oauth2orize.revoke}} middleware requires a {{server}} argument", 60 | "f24b75ecdc45edb84b0c9fec3b6f1e5b": "Unable to load {{OAuth 2.0}} transaction: {0}", 61 | "f483b2bebd08d285c7009c6812f5ba24": "Access token is expired", 62 | "f50708df489d7811db692c0b601483f8": "Missing required parameter: {{client_id}}", 63 | "fa925eb4771bd2897f14b1de78ca0ed2": "Invalid subject: {0}", 64 | "fcdd5cf7956698312e899ddb708abbaf": "missing assertion parameter", 65 | "fef19f407c562658e0132f1625ce968b": "Unauthorized grant type: {0}", 66 | "ff7883d90a5fe850e026885759165406": "Invalid resource owner credentials" 67 | } 68 | -------------------------------------------------------------------------------- /intl/es/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "06f6133efc10bf1f9a2c6b5161c66fba": "Cuerpo de solicitud no analizado. Utilice middleware {{bodyParser}}.", 3 | "083123c0a745a514ce06fa527c151a46": "El middleware {{oauth2orize.authorization}} requiere un argumento {{server}}", 4 | "092f3dd9c9bde61eed97f67459b46a7e": "Tipo de respuesta no soportado: {0}", 5 | "102a3213ff01fc1b03faa5cbe720e6c0": "Código de autorización no válido", 6 | "10b283f781f47e879e25e3b3b84f85e3": "Permiso denegado por {0}", 7 | "12df3715215d39fdb1c5c19775091f31": "{{OAuth2orize}} requiere analizar el cuerpo. ¿Ha olvidado {{app.use(express.bodyParser())}}?", 8 | "14b06036ad206e2b038840c24e677b4d": "{{OAuth2orize}} requiere soporte de transacción. ¿Ha olvidado {{oauth2orize.transactionLoader(...)}}?", 9 | "19d7beb3c393b20162c2c43135b4f1c0": "El código de autorización ha caducado", 10 | "1e1b2073df0a8963670e9ed1e181dfe8": "{{JWT}} no válido: {0}", 11 | "24ff616d05fe6b8dca8859d9dafa729e": "Cliente no válido", 12 | "2caa676b18561101c92e69d70820b1bf": "{{OAuth2orize}} requiere soporte de {{session}}. ¿Ha olvidado {{app.use(express.session(...))}}?", 13 | "37086a106da98d5322d134d7905d1817": "Falta el parámetro obligatorio: {{code}}", 14 | "373b2ad70311b6537ad42719088da022": "No se ha podido deserializar el cliente. Registre la función de deserialización utilizando {{deserializeClient()}}.", 15 | "3bffb3bbef4312d6bcbabd3240e79ef2": "El otorgamiento de {{oauth2orize.code}} requiere una devolución de llamada {{issue}}", 16 | "3cfcae051965e0da5f704a334e1e884c": "Discrepancias de id de cliente", 17 | "43a5b5bf0c7dd0bf5fec2601fe347245": "Solicitud no válida: falta {{redirect_uri}}", 18 | "4428b355c8ba3e248b8fc0857e2181a0": "Tipo de otorgamiento no soportado: {0}", 19 | "452b7bd4aed1b69b7c20fb701377c4eb": "{{redirectURI}} no autorizado: {0}", 20 | "47db77dd8ab3aa3c3ec1e6c955c0cc01": "Falta el parámetro obligatorio: {{username}}", 21 | "53c21d3a92686e2956d527d097e1e1b9": "La señal de acceso tiene un {{user id}} no válido: {0}", 22 | "54d8df1f46d3358dd33ba274a537b519": "Tipo de señal no soportado: {0}", 23 | "5b853ac61fab20ec62d53e183e067ec3": "No se ha podido serializar el cliente. Registre la función de serialización utilizando {{serializeClient()}}.", 24 | "5bc4d117f87ba20efb8cdd4c988ed46d": "El middleware {{oauth2orize.transactionLoader}} requiere un argumento {{server}}", 25 | "6d3b5c2b2c7c20cd8907a0b090f0e89c": "Señal de renovación no válida", 26 | "6e0122e493bd949f408c1421fc757b95": "No es posible emitir redirección para la transacción {{OAuth 2.0}}", 27 | "7175ea69be895be338ca9f9168268dab": "El middleware {{oauth2orize.decision}} requiere un argumento {{server}}", 28 | "740f3fb2bd1358d65943e735224d23e5": "Falta el parámetro obligatorio: {{refresh_token}}", 29 | "76d075ea0325d32667fad67c446e469b": "{{JWT}} no válido", 30 | "8000aa2c64d9c95c406053764fc33f64": "Cliente no autorizado", 31 | "83459aaa8e2d81c7fad2b899ad0cbf57": "El componente {{OAuth2}} no se ha configurado para esta aplicación.", 32 | "839544ec984d6290cd45669efdd39699": "Discrepancias de {{uri}} de redirección", 33 | "8782860f8d60f2bdb6f67d623dd7e51f": "El middleware {{oauth2orize.authorization}} requiere una función {{validate}}", 34 | "9508d060bc6fd6e25cb4d0c00ea0480d": "Ámbito insuficiente", 35 | "a198c4335c42739230d7d8afacdc109d": "El middleware de intercambio {{OAuth 2.0 jwtBearer}} requiere una función {{issue}}.", 36 | "a23d7ec09a60c8bbd119d8287d8b5805": "El middleware {{oauth2orize.revoke}} requiere una función {{revokeToken}}", 37 | "a2f3ad97b7b05618b6722b8f07e9f805": "La estrategia portadora de {{OAuth 2.0 JWT}} requiere una devolución de llamada verify", 38 | "a7b39a5a13fdba4772a83e07cb864156": "No es posible cargar transacciones {{OAuth 2.0}} desde la sesión", 39 | "a82c6b0f0db10b6e198e99068e765570": "La estrategia portadora de {{OAuth 2.0 JWT}} requiere una opción audience", 40 | "aaee2c79ab90ccc63b9d46795e19620a": "El intercambio {{oauth2orize.clientCredentials}} requiere una devolución de llamada issue", 41 | "ae02475e560f64afdcf6d02bc80dcb0e": "Credenciales de cliente no válidas", 42 | "b1af8f34c3d25bd59189205046665bfd": "Falta parámetro obligatorio: {0}", 43 | "b1eb21b6d32dde679f9b4bf0b2e0939d": "{{MACStrategy}} requiere una devolución de llamada verify", 44 | "bac74f7415259e303903cfc8a7bcc4df": "El middleware {{oauth2orize.token}} requiere un argumento {{server}}", 45 | "bcb1c003530e6fb715ad605ea7fe83d9": "El otorgamiento de {{oauth2orize.token}} requiere una devolución de llamada {{issue}}", 46 | "cbd12265f4ab78b30a0977e37aefcf37": "Falta el parámetro obligatorio: {{password}}", 47 | "cdee717bf439af4c84eabb54b82c13af": "El intercambio {{oauth2orize.authorizationCode}} requiere una devolución de llamada issue", 48 | "d36b1a9f8719a56a091ed6c89d3cd1fa": "Solicitud denegada por el servidor de autorización", 49 | "d3dd8b2220bba70a6e7e44af24a4157c": "Falta el parámetro obligatorio: {{token}}", 50 | "d837f7c0309bf4816cbbb22b57473733": "El intercambio {{oauth2orize.password}} requiere una devolución de llamada {{issue}}", 51 | "d83b55a5dfd3e16ca22699e39b072f3f": "La señal de acceso tiene un {{app id}} no válido: {0}", 52 | "db8b02ad229f45cbb12e0d9845b09eb2": "La estrategia portadora de {{OAuth 2.0 JWT}} requiere una devolución de llamada keying", 53 | "e173a3cecca19bcbf528408adc001750": "Tipo de respuesta no autorizado: {0}", 54 | "e82c91e82424949d4390135e5e8adf1c": "Señal {{MAC}} no válida", 55 | "eb30f051fcf0e7338bf4d8489f583378": "{{scope}} no autorizado: {0}", 56 | "ec30fea412580b611d7a274ee1163e5c": "Falta el parámetro obligatorio: {{response_type}}", 57 | "ec9ddf242c3da3b5cf44def6398706ec": "El intercambio {{oauth2orize.refreshToken}} requiere una devolución de llamada {{issue}}", 58 | "ed5c8e0055b1cae433e4c393ae04d555": "Elementos no válidos: {0}", 59 | "f06abf2e08aba65a62f4486bc2418413": "El middleware {{oauth2orize.revoke}} requiere un argumento {{server}}", 60 | "f24b75ecdc45edb84b0c9fec3b6f1e5b": "No se puede cargar la transacción {{OAuth 2.0}}: {0}", 61 | "f483b2bebd08d285c7009c6812f5ba24": "La señal de acceso ha caducado", 62 | "f50708df489d7811db692c0b601483f8": "Falta el parámetro obligatorio: {{client_id}}", 63 | "fa925eb4771bd2897f14b1de78ca0ed2": "Asunto no válido: {0}", 64 | "fcdd5cf7956698312e899ddb708abbaf": "falta parámetro de aserción", 65 | "fef19f407c562658e0132f1625ce968b": "Tipo de otorgamiento no autorizado: {0}", 66 | "ff7883d90a5fe850e026885759165406": "Credenciales de propietario de recurso no válidas" 67 | } 68 | 69 | -------------------------------------------------------------------------------- /intl/fr/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "06f6133efc10bf1f9a2c6b5161c66fba": "Corps de demande non analysé. Utilisez le middleware {{bodyParser}}.", 3 | "083123c0a745a514ce06fa527c151a46": "Le middleware {{oauth2orize.authorization}} requiert un argument {{server}}", 4 | "092f3dd9c9bde61eed97f67459b46a7e": "Type de réponse non pris en charge : {0}", 5 | "102a3213ff01fc1b03faa5cbe720e6c0": "Code d'autorisation non valide", 6 | "10b283f781f47e879e25e3b3b84f85e3": "Accès refusé par {0}", 7 | "12df3715215d39fdb1c5c19775091f31": "{{OAuth2orize}} exige une analyse du corps. Avez-vous oublié {{app.use(express.bodyParser())}} ?", 8 | "14b06036ad206e2b038840c24e677b4d": "{{OAuth2orize}} requiert le support de transaction. Avez-vous oublié {{oauth2orize.transactionLoader(...)}} ?", 9 | "19d7beb3c393b20162c2c43135b4f1c0": "Le code d'autorisation a expiré", 10 | "1e1b2073df0a8963670e9ed1e181dfe8": "{{JWT}} non valide : {0}", 11 | "24ff616d05fe6b8dca8859d9dafa729e": "Client non valide", 12 | "2caa676b18561101c92e69d70820b1bf": "{{OAuth2orize}} requiert le support de {{session}}. Avez-vous oublié {{app.use(express.session(...))}} ?", 13 | "37086a106da98d5322d134d7905d1817": "Paramètre obligatoire manquant : {{code}}", 14 | "373b2ad70311b6537ad42719088da022": "Echec de la désérialisation du client. Enregistrez la fonction de désérialisation en utilisant {{deserializeClient()}}.", 15 | "3bffb3bbef4312d6bcbabd3240e79ef2": "L'octroi {{oauth2orize.code}} requiert {{issue}} callback", 16 | "3cfcae051965e0da5f704a334e1e884c": "Non-concordances d'ID client", 17 | "43a5b5bf0c7dd0bf5fec2601fe347245": "Demande non valide : {{redirect_uri}} manquante", 18 | "4428b355c8ba3e248b8fc0857e2181a0": "Type d'octroi non pris en charge : {0}", 19 | "452b7bd4aed1b69b7c20fb701377c4eb": "{{redirectURI}} non autorisée : {0}", 20 | "47db77dd8ab3aa3c3ec1e6c955c0cc01": "Paramètre obligatoire manquant : {{username}}", 21 | "53c21d3a92686e2956d527d097e1e1b9": "Le jeton d'accès a un {{user id}} non valide : {0}", 22 | "54d8df1f46d3358dd33ba274a537b519": "Type de jeton non pris en charge : {0}", 23 | "5b853ac61fab20ec62d53e183e067ec3": "Echec de la sérialisation du client. Enregistrez la fonction de sérialisation en utilisant {{serializeClient()}}.", 24 | "5bc4d117f87ba20efb8cdd4c988ed46d": "Le middleware {{oauth2orize.transactionLoader}} requiert un argument {{server}}", 25 | "6d3b5c2b2c7c20cd8907a0b090f0e89c": "Jeton d'actualisation non valide", 26 | "6e0122e493bd949f408c1421fc757b95": "Impossible de lancer la redirection pour la transaction {{OAuth 2.0}}", 27 | "7175ea69be895be338ca9f9168268dab": "Le middleware {{oauth2orize.decision}} requiert un argument {{server}}", 28 | "740f3fb2bd1358d65943e735224d23e5": "Paramètre obligatoire manquant : {{refresh_token}}", 29 | "76d075ea0325d32667fad67c446e469b": "{{JWT}} non valide", 30 | "8000aa2c64d9c95c406053764fc33f64": "Client non autorisé", 31 | "83459aaa8e2d81c7fad2b899ad0cbf57": "Le composant {{OAuth2}} n'a pas été configuré pour cette application.", 32 | "839544ec984d6290cd45669efdd39699": "Non-concordances d'{{uri}} de réacheminement", 33 | "8782860f8d60f2bdb6f67d623dd7e51f": "Le middleware {{oauth2orize.authorization}} requiert une fonction {{validate}}", 34 | "9508d060bc6fd6e25cb4d0c00ea0480d": "Portée insuffisante", 35 | "a198c4335c42739230d7d8afacdc109d": "Le middleware d'échange {{OAuth 2.0 jwtBearer}} requiert une fonction {{issue}}.", 36 | "a23d7ec09a60c8bbd119d8287d8b5805": "Le middleware {{oauth2orize.revoke}} requiert une fonction {{revokeToken}}", 37 | "a2f3ad97b7b05618b6722b8f07e9f805": "La stratégie bearer {{OAuth 2.0 JWT}} requiert verify callback", 38 | "a7b39a5a13fdba4772a83e07cb864156": "Impossible de charger les transactions {{OAuth 2.0}} à partir de la session", 39 | "a82c6b0f0db10b6e198e99068e765570": "La stratégie bearer {{OAuth 2.0 JWT}} requiert une option audience", 40 | "aaee2c79ab90ccc63b9d46795e19620a": "L'échange {{oauth2orize.clientCredentials}} requiert issue callback", 41 | "ae02475e560f64afdcf6d02bc80dcb0e": "Données d'identification client non valides", 42 | "b1af8f34c3d25bd59189205046665bfd": "Paramètre obligatoire manquant : {0}", 43 | "b1eb21b6d32dde679f9b4bf0b2e0939d": "{{MACStrategy}} requiert verify callback", 44 | "bac74f7415259e303903cfc8a7bcc4df": "Le middleware {{oauth2orize.token}} requiert un argument {{server}}", 45 | "bcb1c003530e6fb715ad605ea7fe83d9": "L'octroi {{oauth2orize.token}} requiert {{issue}} callback", 46 | "cbd12265f4ab78b30a0977e37aefcf37": "Paramètre obligatoire manquant : {{password}}", 47 | "cdee717bf439af4c84eabb54b82c13af": "L'échange {{oauth2orize.authorizationCode}} requiert issue callback", 48 | "d36b1a9f8719a56a091ed6c89d3cd1fa": "Demande refusée par le serveur d'autorisation", 49 | "d3dd8b2220bba70a6e7e44af24a4157c": "Paramètre obligatoire manquant : {{token}}", 50 | "d837f7c0309bf4816cbbb22b57473733": "L'échange {{oauth2orize.password}} requiert {{issue}} callback", 51 | "d83b55a5dfd3e16ca22699e39b072f3f": "Le jeton d'accès a un {{app id}} non valide : {0}", 52 | "db8b02ad229f45cbb12e0d9845b09eb2": "La stratégie bearer {{OAuth 2.0 JWT}} requiert keying callback", 53 | "e173a3cecca19bcbf528408adc001750": "Type de réponse non autorisé : {0}", 54 | "e82c91e82424949d4390135e5e8adf1c": "Jeton {{MAC}} non valide", 55 | "eb30f051fcf0e7338bf4d8489f583378": "{{scope}} non autorisée : {0}", 56 | "ec30fea412580b611d7a274ee1163e5c": "Paramètre obligatoire manquant : {{response_type}}", 57 | "ec9ddf242c3da3b5cf44def6398706ec": "L'échange {{oauth2orize.refreshToken}} requiert {{issue}} callback", 58 | "ed5c8e0055b1cae433e4c393ae04d555": "Eléments non valides : {0}", 59 | "f06abf2e08aba65a62f4486bc2418413": "Le middleware {{oauth2orize.revoke}} requiert un argument {{server}}", 60 | "f24b75ecdc45edb84b0c9fec3b6f1e5b": "Impossible de charger la transaction {{OAuth 2.0}} : {0}", 61 | "f483b2bebd08d285c7009c6812f5ba24": "Le jeton d'accès a expiré", 62 | "f50708df489d7811db692c0b601483f8": "Paramètre obligatoire manquant : {{client_id}}", 63 | "fa925eb4771bd2897f14b1de78ca0ed2": "Sujet non valide : {0}", 64 | "fcdd5cf7956698312e899ddb708abbaf": "paramètre d'assertion manquant", 65 | "fef19f407c562658e0132f1625ce968b": "Type d'octroi non autorisé : {0}", 66 | "ff7883d90a5fe850e026885759165406": "Données d'identification du propriétaire de la ressource non valides" 67 | } 68 | 69 | -------------------------------------------------------------------------------- /intl/it/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "06f6133efc10bf1f9a2c6b5161c66fba": "Corpo della richiesta non analizzato. Utilizzare il middleware {{bodyParser}}.", 3 | "083123c0a745a514ce06fa527c151a46": "Il middleware {{oauth2orize.authorization}} richiede un argomento {{server}}", 4 | "092f3dd9c9bde61eed97f67459b46a7e": "Tipo di risposta non supportato: {0}", 5 | "102a3213ff01fc1b03faa5cbe720e6c0": "Codice di autorizzazione non valido", 6 | "10b283f781f47e879e25e3b3b84f85e3": "Autorizzazione negata da {0}", 7 | "12df3715215d39fdb1c5c19775091f31": "{{OAuth2orize}} richiede l'analisi del corpo. {{app.use(express.bodyParser())}} dimenticato?", 8 | "14b06036ad206e2b038840c24e677b4d": "{{OAuth2orize}} richiede il supporto della transazione. {{oauth2orize.transactionLoader(...)}} dimenticato?", 9 | "19d7beb3c393b20162c2c43135b4f1c0": "Codice di autorizzazione scaduto", 10 | "1e1b2073df0a8963670e9ed1e181dfe8": "{{JWT}} non valido: {0}", 11 | "24ff616d05fe6b8dca8859d9dafa729e": "Client non valido", 12 | "2caa676b18561101c92e69d70820b1bf": "{{OAuth2orize}} richiede il supporto {{session}}. {{app.use(express.session(...))}} dimenticato?", 13 | "37086a106da98d5322d134d7905d1817": "Parametro obbligatorio mancante: {{code}}", 14 | "373b2ad70311b6537ad42719088da022": "Impossibile deserializzare il client. Registrare la funzione di deserializzazione utilizzando {{deserializeClient()}}.", 15 | "3bffb3bbef4312d6bcbabd3240e79ef2": "La concessione {{oauth2orize.code}} richiede un callback {{issue}}", 16 | "3cfcae051965e0da5f704a334e1e884c": "ID client non corrispondente", 17 | "43a5b5bf0c7dd0bf5fec2601fe347245": "Richiesta non valida: {{redirect_uri}} mancante", 18 | "4428b355c8ba3e248b8fc0857e2181a0": "Tipo di concessione non supportato: {0}", 19 | "452b7bd4aed1b69b7c20fb701377c4eb": "{{redirectURI}} non autorizzato: {0}", 20 | "47db77dd8ab3aa3c3ec1e6c955c0cc01": "Parametro obbligatorio mancante: {{username}}", 21 | "53c21d3a92686e2956d527d097e1e1b9": "Il token di accesso ha un {{user id}} non valido: {0}", 22 | "54d8df1f46d3358dd33ba274a537b519": "Tipo di token non supportato: {0}", 23 | "5b853ac61fab20ec62d53e183e067ec3": "Impossibile serializzare il client. Registrare la funzione di serializzazione utilizzando {{serializeClient()}}.", 24 | "5bc4d117f87ba20efb8cdd4c988ed46d": "Il middleware {{oauth2orize.transactionLoader}} richiede un argomento {{server}}", 25 | "6d3b5c2b2c7c20cd8907a0b090f0e89c": "Token di aggiornamento non valido", 26 | "6e0122e493bd949f408c1421fc757b95": "Impossibile inviare il reindirizzamento per la transazione {{OAuth 2.0}}", 27 | "7175ea69be895be338ca9f9168268dab": "Il middleware {{oauth2orize.decision}} richiede un argomento {{server}}", 28 | "740f3fb2bd1358d65943e735224d23e5": "Parametro obbligatorio mancante: {{refresh_token}}", 29 | "76d075ea0325d32667fad67c446e469b": "{{JWT}} non valido", 30 | "8000aa2c64d9c95c406053764fc33f64": "Client non autorizzato", 31 | "83459aaa8e2d81c7fad2b899ad0cbf57": "Il componente {{OAuth2}} non è stato configurato per questa applicazione.", 32 | "839544ec984d6290cd45669efdd39699": "{{uri}} di reindirizzamento non corrispondente", 33 | "8782860f8d60f2bdb6f67d623dd7e51f": "Il middleware {{oauth2orize.authorization}} richiede una funzione {{validate}}", 34 | "9508d060bc6fd6e25cb4d0c00ea0480d": "Ambito insufficiente", 35 | "a198c4335c42739230d7d8afacdc109d": "Il middleware di scambio {{OAuth 2.0 jwtBearer}} richiede una funzione {{issue}}.", 36 | "a23d7ec09a60c8bbd119d8287d8b5805": "Il middleware {{oauth2orize.revoke}} richiede una funzione {{revokeToken}}", 37 | "a2f3ad97b7b05618b6722b8f07e9f805": "La strategia bearer {{OAuth 2.0 JWT}} richiede un callback di verifica", 38 | "a7b39a5a13fdba4772a83e07cb864156": "Impossibile caricare le transazioni {{OAuth 2.0}} dalla sessione", 39 | "a82c6b0f0db10b6e198e99068e765570": "La strategia bearer {{OAuth 2.0 JWT}} richiede un'opzione del destinatario", 40 | "aaee2c79ab90ccc63b9d46795e19620a": "Lo scambio {{oauth2orize.clientCredentials}} richiede un callback di invio", 41 | "ae02475e560f64afdcf6d02bc80dcb0e": "Credenziali client non valide", 42 | "b1af8f34c3d25bd59189205046665bfd": "Parametro obbligatorio mancante: {0}", 43 | "b1eb21b6d32dde679f9b4bf0b2e0939d": "{{MACStrategy}} richiede un callback di verifica", 44 | "bac74f7415259e303903cfc8a7bcc4df": "Il middleware {{oauth2orize.token}} richiede un argomento {{server}}", 45 | "bcb1c003530e6fb715ad605ea7fe83d9": "La concessione {{oauth2orize.token}} richiede un callback {{issue}}", 46 | "cbd12265f4ab78b30a0977e37aefcf37": "Parametro obbligatorio mancante: {{password}}", 47 | "cdee717bf439af4c84eabb54b82c13af": "Lo scambio {{oauth2orize.authorizationCode}} richiede un callback di invio", 48 | "d36b1a9f8719a56a091ed6c89d3cd1fa": "Richiesta negata dal server delle autorizzazioni", 49 | "d3dd8b2220bba70a6e7e44af24a4157c": "Parametro obbligatorio mancante: {{token}}", 50 | "d837f7c0309bf4816cbbb22b57473733": "Lo scambio {{oauth2orize.password}} richiede un callback {{issue}}", 51 | "d83b55a5dfd3e16ca22699e39b072f3f": "Il token di accesso ha un {{app id}} non valido: {0}", 52 | "db8b02ad229f45cbb12e0d9845b09eb2": "La strategia bearer {{OAuth 2.0 JWT}} richiede un callback di creazione chiavi", 53 | "e173a3cecca19bcbf528408adc001750": "Tipo di risposta non autorizzato: {0}", 54 | "e82c91e82424949d4390135e5e8adf1c": "Token {{MAC}} non valido", 55 | "eb30f051fcf0e7338bf4d8489f583378": "{{scope}} non autorizzato: {0}", 56 | "ec30fea412580b611d7a274ee1163e5c": "Parametro obbligatorio mancante: {{response_type}}", 57 | "ec9ddf242c3da3b5cf44def6398706ec": "Lo scambio {{oauth2orize.refreshToken}} richiede un callback {{issue}}", 58 | "ed5c8e0055b1cae433e4c393ae04d555": "Elementi non validi: {0}", 59 | "f06abf2e08aba65a62f4486bc2418413": "Il middleware {{oauth2orize.revoke}} richiede un argomento {{server}}", 60 | "f24b75ecdc45edb84b0c9fec3b6f1e5b": "Impossibile caricare la transazione {{OAuth 2.0}}: {0}", 61 | "f483b2bebd08d285c7009c6812f5ba24": "Il token di accesso è scaduto", 62 | "f50708df489d7811db692c0b601483f8": "Parametro obbligatorio mancante: {{client_id}}", 63 | "fa925eb4771bd2897f14b1de78ca0ed2": "Oggetto non valido: {0}", 64 | "fcdd5cf7956698312e899ddb708abbaf": "parametro dell'asserzione mancante", 65 | "fef19f407c562658e0132f1625ce968b": "Tipo di concessione non autorizzato: {0}", 66 | "ff7883d90a5fe850e026885759165406": "Credenziali del proprietario della risorsa non valide" 67 | } 68 | 69 | -------------------------------------------------------------------------------- /intl/ja/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "06f6133efc10bf1f9a2c6b5161c66fba": "要求本文が解析されていません。 {{bodyParser}} ミドルウェアを使用してください。", 3 | "083123c0a745a514ce06fa527c151a46": "{{oauth2orize.authorization}} ミドルウェアには {{server}} 引数が必要です", 4 | "092f3dd9c9bde61eed97f67459b46a7e": "サポートされない応答タイプ: {0}", 5 | "102a3213ff01fc1b03faa5cbe720e6c0": "無効な許可コード", 6 | "10b283f781f47e879e25e3b3b84f85e3": "許可は {0} によって拒否されました", 7 | "12df3715215d39fdb1c5c19775091f31": "{{OAuth2orize}} では本文の解析が必要です。 {{app.use(express.bodyParser())}} を忘れていませんか?", 8 | "14b06036ad206e2b038840c24e677b4d": "{{OAuth2orize}} にはトランザクション・サポートが必要です。 {{oauth2orize.transactionLoader(...)}} を忘れていませんか?", 9 | "19d7beb3c393b20162c2c43135b4f1c0": "許可コードが期限切れです", 10 | "1e1b2073df0a8963670e9ed1e181dfe8": "無効な {{JWT}}: {0}", 11 | "24ff616d05fe6b8dca8859d9dafa729e": "無効なクライアント", 12 | "2caa676b18561101c92e69d70820b1bf": "{{OAuth2orize}} には {{session}} サポートが必要です。 {{app.use(express.session(...))}} を忘れていませんか?", 13 | "37086a106da98d5322d134d7905d1817": "必須パラメーターが欠落しています: {{code}}", 14 | "373b2ad70311b6537ad42719088da022": "クライアントのデシリアライズに失敗しました。 {{deserializeClient()}} を使用してデシリアライゼーション関数を登録します。", 15 | "3bffb3bbef4312d6bcbabd3240e79ef2": "{{oauth2orize.code}} 権限付与には {{issue}} コールバックが必要です", 16 | "3cfcae051965e0da5f704a334e1e884c": "クライアント ID が一致しません", 17 | "43a5b5bf0c7dd0bf5fec2601fe347245": "無効な要求: {{redirect_uri}} がありません", 18 | "4428b355c8ba3e248b8fc0857e2181a0": "サポートされない権限付与タイプ: {0}", 19 | "452b7bd4aed1b69b7c20fb701377c4eb": "無許可の {{redirectURI}}: {0}", 20 | "47db77dd8ab3aa3c3ec1e6c955c0cc01": "必須パラメーターが欠落しています: {{username}}", 21 | "53c21d3a92686e2956d527d097e1e1b9": "アクセス・トークンには無効な {{user id}} があります: {0}", 22 | "54d8df1f46d3358dd33ba274a537b519": "サポートされないトークン・タイプ: {0}", 23 | "5b853ac61fab20ec62d53e183e067ec3": "クライアントのシリアライズに失敗しました。 {{serializeClient()}} を使用してシリアライゼーション関数を登録します。", 24 | "5bc4d117f87ba20efb8cdd4c988ed46d": "{{oauth2orize.transactionLoader}} ミドルウェアには {{server}} 引数が必要です", 25 | "6d3b5c2b2c7c20cd8907a0b090f0e89c": "無効なリフレッシュ・トークン", 26 | "6e0122e493bd949f408c1421fc757b95": "{{OAuth 2.0}} トランザクションのリダイレクトを発行できません", 27 | "7175ea69be895be338ca9f9168268dab": "{{oauth2orize.decision}} ミドルウェアには {{server}} 引数が必要です", 28 | "740f3fb2bd1358d65943e735224d23e5": "必須パラメーターが欠落しています: {{refresh_token}}", 29 | "76d075ea0325d32667fad67c446e469b": "無効な {{JWT}}", 30 | "8000aa2c64d9c95c406053764fc33f64": "無許可のクライアント", 31 | "83459aaa8e2d81c7fad2b899ad0cbf57": "このアプリケーションに対して {{OAuth2}} コンポーネントは構成されませんでした。", 32 | "839544ec984d6290cd45669efdd39699": "リダイレクト {{uri}} が一致しません", 33 | "8782860f8d60f2bdb6f67d623dd7e51f": "{{oauth2orize.authorization}} ミドルウェアには {{validate}} 関数が必要です", 34 | "9508d060bc6fd6e25cb4d0c00ea0480d": "スコープが不十分です", 35 | "a198c4335c42739230d7d8afacdc109d": "{{OAuth 2.0 jwtBearer}} 交換ミドルウェアには {{issue}} 関数が必要です。", 36 | "a23d7ec09a60c8bbd119d8287d8b5805": "{{oauth2orize.revoke}} ミドルウェアには {{revokeToken}} 関数が必要です", 37 | "a2f3ad97b7b05618b6722b8f07e9f805": "{{OAuth 2.0 JWT}} ベアラー戦略には検証コールバックが必要です", 38 | "a7b39a5a13fdba4772a83e07cb864156": "セッションから {{OAuth 2.0}} トランザクションをロードできません", 39 | "a82c6b0f0db10b6e198e99068e765570": "{{OAuth 2.0 JWT}} ベアラー戦略には audience オプションが必要です", 40 | "aaee2c79ab90ccc63b9d46795e19620a": "{{oauth2orize.clientCredentials}} 交換には発行コールバックが必要です", 41 | "ae02475e560f64afdcf6d02bc80dcb0e": "無効なクライアント資格情報", 42 | "b1af8f34c3d25bd59189205046665bfd": "必須パラメーターが欠落しています: {0}", 43 | "b1eb21b6d32dde679f9b4bf0b2e0939d": "{{MACStrategy}} には検証コールバックが必要です", 44 | "bac74f7415259e303903cfc8a7bcc4df": "{{oauth2orize.token}} ミドルウェアには {{server}} 引数が必要です", 45 | "bcb1c003530e6fb715ad605ea7fe83d9": "{{oauth2orize.token}} 権限付与には {{issue}} コールバックが必要です", 46 | "cbd12265f4ab78b30a0977e37aefcf37": "必須パラメーターが欠落しています: {{password}}", 47 | "cdee717bf439af4c84eabb54b82c13af": "{{oauth2orize.authorizationCode}} 交換には発行コールバックが必要です", 48 | "d36b1a9f8719a56a091ed6c89d3cd1fa": "要求は許可サーバーによって拒否されました", 49 | "d3dd8b2220bba70a6e7e44af24a4157c": "必須パラメーターが欠落しています: {{token}}", 50 | "d837f7c0309bf4816cbbb22b57473733": "{{oauth2orize.password}} 交換には {{issue}} コールバックが必要です", 51 | "d83b55a5dfd3e16ca22699e39b072f3f": "アクセス・トークンには無効な {{app id}} があります: {0}", 52 | "db8b02ad229f45cbb12e0d9845b09eb2": "{{OAuth 2.0 JWT}} ベアラー戦略にはキー入力コールバックが必要です", 53 | "e173a3cecca19bcbf528408adc001750": "無許可の応答タイプ: {0}", 54 | "e82c91e82424949d4390135e5e8adf1c": "無効な {{MAC}} トークン", 55 | "eb30f051fcf0e7338bf4d8489f583378": "無許可の {{scope}}: {0}", 56 | "ec30fea412580b611d7a274ee1163e5c": "必須パラメーターが欠落しています: {{response_type}}", 57 | "ec9ddf242c3da3b5cf44def6398706ec": "{{oauth2orize.refreshToken}} 交換には {{issue}} コールバックが必要です", 58 | "ed5c8e0055b1cae433e4c393ae04d555": "無効な項目: {0}", 59 | "f06abf2e08aba65a62f4486bc2418413": "{{oauth2orize.revoke}} ミドルウェアには {{server}} 引数が必要です", 60 | "f24b75ecdc45edb84b0c9fec3b6f1e5b": "{{OAuth 2.0}} トランザクションをロードできません: {0}", 61 | "f483b2bebd08d285c7009c6812f5ba24": "アクセス・トークンが期限切れです", 62 | "f50708df489d7811db692c0b601483f8": "必須パラメーターが欠落しています: {{client_id}}", 63 | "fa925eb4771bd2897f14b1de78ca0ed2": "無効な件名: {0}", 64 | "fcdd5cf7956698312e899ddb708abbaf": "アサーション・パラメーターが欠落しています", 65 | "fef19f407c562658e0132f1625ce968b": "無許可の権限付与タイプ: {0}", 66 | "ff7883d90a5fe850e026885759165406": "無効なリソース所有者資格情報" 67 | } 68 | 69 | -------------------------------------------------------------------------------- /intl/ko/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "06f6133efc10bf1f9a2c6b5161c66fba": "요청 본문을 구문 분석할 수 없습니다. {{bodyParser}} 미들웨어를 사용하십시오.", 3 | "083123c0a745a514ce06fa527c151a46": "{{oauth2orize.authorization}} 미들웨어에 {{server}} 인수가 필요함", 4 | "092f3dd9c9bde61eed97f67459b46a7e": "지원되지 않는 응답 유형: {0}", 5 | "102a3213ff01fc1b03faa5cbe720e6c0": "올바르지 않은 권한 코드", 6 | "10b283f781f47e879e25e3b3b84f85e3": "{0}이(가) 권한을 거부함", 7 | "12df3715215d39fdb1c5c19775091f31": "{{OAuth2orize}}에서는 본문 구문 분석이 필요합니다. {{app.use(express.bodyParser())}}을(를) 잊으셨습니까?", 8 | "14b06036ad206e2b038840c24e677b4d": "{{OAuth2orize}}에는 트랜잭션 지원이 필요합니다. {{oauth2orize.transactionLoader(...)}}을(를) 잊으셨습니까?", 9 | "19d7beb3c393b20162c2c43135b4f1c0": "권한 코드가 만료됨", 10 | "1e1b2073df0a8963670e9ed1e181dfe8": "올바르지 않은 {{JWT}}: {0}", 11 | "24ff616d05fe6b8dca8859d9dafa729e": "올바르지 않은 클라이언트", 12 | "2caa676b18561101c92e69d70820b1bf": "{{OAuth2orize}}에는 {{session}} 지원이 필요합니다. {{app.use(express.session(...))}}을(를) 잊으셨습니까?", 13 | "37086a106da98d5322d134d7905d1817": "필수 매개변수가 누락됨: {{code}}", 14 | "373b2ad70311b6537ad42719088da022": "클라이언트를 직렬화 해제하는 데 실패했습니다. {{deserializeClient()}}을(를) 사용하여 직렬화 해제 기능을 등록하십시오.", 15 | "3bffb3bbef4312d6bcbabd3240e79ef2": "{{oauth2orize.code}} 부여에 {{issue}} 콜백이 필요함", 16 | "3cfcae051965e0da5f704a334e1e884c": "클라이언트 ID 불일치", 17 | "43a5b5bf0c7dd0bf5fec2601fe347245": "올바르지 않은 요청: {{redirect_uri}}이(가) 누락됨", 18 | "4428b355c8ba3e248b8fc0857e2181a0": "지원되지 않는 권한 부여 유형: {0}", 19 | "452b7bd4aed1b69b7c20fb701377c4eb": "권한이 없는 {{redirectURI}}: {0}", 20 | "47db77dd8ab3aa3c3ec1e6c955c0cc01": "필수 매개변수가 누락됨: {{username}}", 21 | "53c21d3a92686e2956d527d097e1e1b9": "액세스 토큰에 올바르지 않은 {{user id}}가 있음: {0}", 22 | "54d8df1f46d3358dd33ba274a537b519": "지원되지 않는 토큰 유형: {0}", 23 | "5b853ac61fab20ec62d53e183e067ec3": "클라이언트를 직렬화하는 데 실패했습니다. {{serializeClient()}}을(를) 사용하여 직렬화 기능을 등록하십시오.", 24 | "5bc4d117f87ba20efb8cdd4c988ed46d": "{{oauth2orize.transactionLoader}} 미들웨어에 {{server}} 인수가 필요함", 25 | "6d3b5c2b2c7c20cd8907a0b090f0e89c": "올바르지 않은 새로 고치기 토큰", 26 | "6e0122e493bd949f408c1421fc757b95": "{{OAuth 2.0}} 트랜잭션에 대한 경로 재지정을 발행할 수 없음", 27 | "7175ea69be895be338ca9f9168268dab": "{{oauth2orize.decision}} 미들웨어에 {{server}} 인수가 필요함", 28 | "740f3fb2bd1358d65943e735224d23e5": "필수 매개변수가 누락됨: {{refresh_token}}", 29 | "76d075ea0325d32667fad67c446e469b": "올바르지 않은 {{JWT}}", 30 | "8000aa2c64d9c95c406053764fc33f64": "권한이 없는 클라이언트", 31 | "83459aaa8e2d81c7fad2b899ad0cbf57": "이 애플리케이션에 대해 {{OAuth2}} 컴포넌트가 구성되지 않았습니다.", 32 | "839544ec984d6290cd45669efdd39699": "{{uri}} 불일치 항목 경로 재지정", 33 | "8782860f8d60f2bdb6f67d623dd7e51f": "{{oauth2orize.authorization}} 미들웨어에 {{validate}} 기능이 필요함", 34 | "9508d060bc6fd6e25cb4d0c00ea0480d": "충분하지 않은 범위", 35 | "a198c4335c42739230d7d8afacdc109d": "{{OAuth 2.0 jwtBearer}} 교환 미들웨어에 {{issue}} 기능이 필요합니다.", 36 | "a23d7ec09a60c8bbd119d8287d8b5805": "{{oauth2orize.revoke}} 미들웨어에 {{revokeToken}} 기능이 필요함", 37 | "a2f3ad97b7b05618b6722b8f07e9f805": "{{OAuth 2.0 JWT}} 전달자 전략에 확인 콜백이 필요함", 38 | "a7b39a5a13fdba4772a83e07cb864156": "세션에서 {{OAuth 2.0}} 트랜잭션을 로드할 수 없음", 39 | "a82c6b0f0db10b6e198e99068e765570": "{{OAuth 2.0 JWT}} 전달자 전략에 대상(audience) 옵션이 필요함", 40 | "aaee2c79ab90ccc63b9d46795e19620a": "{{oauth2orize.clientCredentials}} 교환에 발행 콜백이 필요함", 41 | "ae02475e560f64afdcf6d02bc80dcb0e": "올바르지 않은 클라이언트 신임 정보", 42 | "b1af8f34c3d25bd59189205046665bfd": "필수 매개변수가 누락됨: {0}", 43 | "b1eb21b6d32dde679f9b4bf0b2e0939d": "{{MACStrategy}}에 확인 콜백이 필요함", 44 | "bac74f7415259e303903cfc8a7bcc4df": "{{oauth2orize.token}} 미들웨어에 {{server}} 인수가 필요함", 45 | "bcb1c003530e6fb715ad605ea7fe83d9": "{{oauth2orize.token}} 부여에 {{issue}} 콜백이 필요함", 46 | "cbd12265f4ab78b30a0977e37aefcf37": "필수 매개변수가 누락됨: {{password}}", 47 | "cdee717bf439af4c84eabb54b82c13af": "{{oauth2orize.authorizationCode}} 교환에 발행 콜백이 필요함", 48 | "d36b1a9f8719a56a091ed6c89d3cd1fa": "권한 부여 서버에서 요청을 거부함", 49 | "d3dd8b2220bba70a6e7e44af24a4157c": "필수 매개변수가 누락됨: {{token}}", 50 | "d837f7c0309bf4816cbbb22b57473733": "{{oauth2orize.password}} 교환에 {{issue}} 콜백이 필요함", 51 | "d83b55a5dfd3e16ca22699e39b072f3f": "액세스 토큰에 올바르지 않은 {{app id}}가 있음: {0}", 52 | "db8b02ad229f45cbb12e0d9845b09eb2": "{{OAuth 2.0 JWT}} 전달자 전략에 키 콜백이 필요함", 53 | "e173a3cecca19bcbf528408adc001750": "권한이 없는 응답 유형: {0}", 54 | "e82c91e82424949d4390135e5e8adf1c": "올바르지 않은 {{MAC}} 토큰", 55 | "eb30f051fcf0e7338bf4d8489f583378": "권한이 없는 {{scope}}: {0}", 56 | "ec30fea412580b611d7a274ee1163e5c": "필수 매개변수가 누락됨: {{response_type}}", 57 | "ec9ddf242c3da3b5cf44def6398706ec": "{{oauth2orize.refreshToken}} 교환에 {{issue}} 콜백이 필요함", 58 | "ed5c8e0055b1cae433e4c393ae04d555": "올바르지 않은 항목: {0}", 59 | "f06abf2e08aba65a62f4486bc2418413": "{{oauth2orize.revoke}} 미들웨어에 {{server}} 인수가 필요함", 60 | "f24b75ecdc45edb84b0c9fec3b6f1e5b": "{{OAuth 2.0}} 트랜잭션을 로드할 수 없음: {0}", 61 | "f483b2bebd08d285c7009c6812f5ba24": "액세스 토큰이 만료됨", 62 | "f50708df489d7811db692c0b601483f8": "필수 매개변수가 누락됨: {{client_id}}", 63 | "fa925eb4771bd2897f14b1de78ca0ed2": "올바르지 않은 주제: {0}", 64 | "fcdd5cf7956698312e899ddb708abbaf": "어설션 매개변수가 누락됨", 65 | "fef19f407c562658e0132f1625ce968b": "권한이 없는 부여 유형: {0}", 66 | "ff7883d90a5fe850e026885759165406": "올바르지 않은 자원 소유자 신임 정보" 67 | } 68 | 69 | -------------------------------------------------------------------------------- /intl/nl/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "06f6133efc10bf1f9a2c6b5161c66fba": "Lopende tekst van opdracht is niet ontleed. Gebruik de {{bodyParser}}-middleware.", 3 | "083123c0a745a514ce06fa527c151a46": "{{oauth2orize.authorization}}-middleware vereist een {{server}}-argument", 4 | "092f3dd9c9bde61eed97f67459b46a7e": "Niet-ondersteund responstype: {0}", 5 | "102a3213ff01fc1b03faa5cbe720e6c0": "Ongeldige machtigingscode", 6 | "10b283f781f47e879e25e3b3b84f85e3": "Toestemming geweigerd door {0}", 7 | "12df3715215d39fdb1c5c19775091f31": "{{OAuth2orize}} vereist ontleding van lopende tekst. Bent u {{app.use(express.bodyParser())}} vergeten?", 8 | "14b06036ad206e2b038840c24e677b4d": "{{OAuth2orize}} vereist transactieondersteuning. Bent u {{oauth2orize.transactionLoader(...)}} vergeten?", 9 | "19d7beb3c393b20162c2c43135b4f1c0": "Machtigingscode is vervallen", 10 | "1e1b2073df0a8963670e9ed1e181dfe8": "Ongeldige {{JWT}}: {0}", 11 | "24ff616d05fe6b8dca8859d9dafa729e": "Ongeldige client", 12 | "2caa676b18561101c92e69d70820b1bf": "{{OAuth2orize}} vereist ondersteuning van {{session}}. Bent u {{app.use(express.session(...))}} vergeten?", 13 | "37086a106da98d5322d134d7905d1817": "Verplichte parameter ontbreekt: {{code}}", 14 | "373b2ad70311b6537ad42719088da022": "Fout tijdens deserialisatie van client. Registreer deserialisatiefunctie met behulp van {{deserializeClient()}}.", 15 | "3bffb3bbef4312d6bcbabd3240e79ef2": "{{issue}}-callback vereist voor verlening van {{oauth2orize.code}}", 16 | "3cfcae051965e0da5f704a334e1e884c": "Niet-overeenkomende client-ID's", 17 | "43a5b5bf0c7dd0bf5fec2601fe347245": "Ongeldige aanvraag: {{redirect_uri}} ontbreekt", 18 | "4428b355c8ba3e248b8fc0857e2181a0": "Niet-ondersteund verleningstype: {0}", 19 | "452b7bd4aed1b69b7c20fb701377c4eb": "Niet-geautoriseerde {{redirectURI}}: {0}", 20 | "47db77dd8ab3aa3c3ec1e6c955c0cc01": "Verplichte parameter ontbreekt: {{username}}", 21 | "53c21d3a92686e2956d527d097e1e1b9": "Toegangstoken heeft ongeldig {{user id}}: {0}", 22 | "54d8df1f46d3358dd33ba274a537b519": "Niet-ondersteund tokentype: {0}", 23 | "5b853ac61fab20ec62d53e183e067ec3": "Fout tijdens serialisatie van client. Registreer serialisatiefunctie met behulp van {{serializeClient()}}.", 24 | "5bc4d117f87ba20efb8cdd4c988ed46d": "{{oauth2orize.transactionLoader}}-middleware vereist een {{server}}-argument", 25 | "6d3b5c2b2c7c20cd8907a0b090f0e89c": "Ongeldig vernieuwingstoken", 26 | "6e0122e493bd949f408c1421fc757b95": "Er kan geen omleidingsroute worden opgegeven voor {{OAuth 2.0}}-transactie", 27 | "7175ea69be895be338ca9f9168268dab": "{{oauth2orize.decision}}-middleware vereist een {{server}}-argument", 28 | "740f3fb2bd1358d65943e735224d23e5": "Verplichte parameter ontbreekt: {{refresh_token}}", 29 | "76d075ea0325d32667fad67c446e469b": "ongeldige {{JWT}}", 30 | "8000aa2c64d9c95c406053764fc33f64": "Niet-geautoriseerde client", 31 | "83459aaa8e2d81c7fad2b899ad0cbf57": "De component {{OAuth2}} is niet geconfigureerd voor deze toepassing.", 32 | "839544ec984d6290cd45669efdd39699": "Niet-overeenkomende {{uri}}-omleidingen", 33 | "8782860f8d60f2bdb6f67d623dd7e51f": "{{oauth2orize.authorization}}-middleware vereist een {{validate}}-functie", 34 | "9508d060bc6fd6e25cb4d0c00ea0480d": "Onvoldoende bereik", 35 | "a198c4335c42739230d7d8afacdc109d": "{{OAuth 2.0 jwtBearer}}-uitwisselingsmiddleware vereist een {{issue}}-functie.", 36 | "a23d7ec09a60c8bbd119d8287d8b5805": "{{oauth2orize.revoke}}-middleware vereist een {{revokeToken}}-functie", 37 | "a2f3ad97b7b05618b6722b8f07e9f805": "Bevestigingscallback vereist voor bearerstrategie van {{OAuth 2.0 JWT}}", 38 | "a7b39a5a13fdba4772a83e07cb864156": "Kan geen {{OAuth 2.0}}-transacties laden vanuit sessie", 39 | "a82c6b0f0db10b6e198e99068e765570": "Doelgroepoptie vereist voor bearerstrategie van {{OAuth 2.0 JWT}}", 40 | "aaee2c79ab90ccc63b9d46795e19620a": "Uitwisseling van {{oauth2orize.clientCredentials}} vereist het opgeven van een callback", 41 | "ae02475e560f64afdcf6d02bc80dcb0e": "Ongeldige legitimatiegegevens van klant", 42 | "b1af8f34c3d25bd59189205046665bfd": "Verplichte parameter ontbreekt: {0}", 43 | "b1eb21b6d32dde679f9b4bf0b2e0939d": "Bevestigingscallback vereist voor {{MACStrategy}}", 44 | "bac74f7415259e303903cfc8a7bcc4df": "{{oauth2orize.token}}-middleware vereist een {{server}}-argument", 45 | "bcb1c003530e6fb715ad605ea7fe83d9": "{{issue}}-callback vereist voor verlening van {{oauth2orize.token}}", 46 | "cbd12265f4ab78b30a0977e37aefcf37": "Verplichte parameter ontbreekt: {{password}}", 47 | "cdee717bf439af4c84eabb54b82c13af": "Uitwisseling van {{oauth2orize.authorizationCode}} vereist het opgeven van een callback", 48 | "d36b1a9f8719a56a091ed6c89d3cd1fa": "Aanvraag geweigerd door autorisatieserver", 49 | "d3dd8b2220bba70a6e7e44af24a4157c": "Verplichte parameter ontbreekt: {{token}}", 50 | "d837f7c0309bf4816cbbb22b57473733": "{{oauth2orize.password}}-uitwisseling vereist een {{issue}}-callback", 51 | "d83b55a5dfd3e16ca22699e39b072f3f": "Toegangstoken heeft ongeldig {{app id}}: {0}", 52 | "db8b02ad229f45cbb12e0d9845b09eb2": "Keying callback vereist voor bearerstrategie van {{OAuth 2.0 JWT}}", 53 | "e173a3cecca19bcbf528408adc001750": "Niet-geautoriseerd responstype: {0}", 54 | "e82c91e82424949d4390135e5e8adf1c": "Ongeldig {{MAC}}-token", 55 | "eb30f051fcf0e7338bf4d8489f583378": "Niet-geautoriseerde {{scope}}: {0}", 56 | "ec30fea412580b611d7a274ee1163e5c": "Verplichte parameter ontbreekt: {{response_type}}", 57 | "ec9ddf242c3da3b5cf44def6398706ec": "{{oauth2orize.refreshToken}}-uitwisseling vereist een {{issue}}-callback", 58 | "ed5c8e0055b1cae433e4c393ae04d555": "Ongeldige items: {0}", 59 | "f06abf2e08aba65a62f4486bc2418413": "{{oauth2orize.revoke}}-middleware vereist een {{server}}-argument", 60 | "f24b75ecdc45edb84b0c9fec3b6f1e5b": "{{OAuth 2.0}}-transactie kan niet worden geladen: {0}", 61 | "f483b2bebd08d285c7009c6812f5ba24": "Toegangstoken is vervallen", 62 | "f50708df489d7811db692c0b601483f8": "Verplichte parameter ontbreekt: {{client_id}}", 63 | "fa925eb4771bd2897f14b1de78ca0ed2": "Ongeldig onderwerp: {0}", 64 | "fcdd5cf7956698312e899ddb708abbaf": "ontbrekende bevestigingsparameter", 65 | "fef19f407c562658e0132f1625ce968b": "Niet-geautoriseerd verleningstype: {0}", 66 | "ff7883d90a5fe850e026885759165406": "Ongeldige legitimatiegegevens voor resource-eigenaar" 67 | } 68 | 69 | -------------------------------------------------------------------------------- /intl/pl/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "06f6133efc10bf1f9a2c6b5161c66fba": "Treść żądania nie została przeanalizowana. Użyj warstwy pośredniej {{bodyParser}}.", 3 | "083123c0a745a514ce06fa527c151a46": "Warstwa pośrednia {{oauth2orize.authorization}} wymaga argumentu {{server}}", 4 | "092f3dd9c9bde61eed97f67459b46a7e": "Nieobsługiwany typ odpowiedzi: {0}", 5 | "102a3213ff01fc1b03faa5cbe720e6c0": "Niepoprawny kod autoryzacji", 6 | "10b283f781f47e879e25e3b3b84f85e3": "Odmowa uprawnień przez {0}", 7 | "12df3715215d39fdb1c5c19775091f31": "Funkcja {{OAuth2orize}} wymaga analizowania treści. Czy zapomniano o metodzie {{app.use(express.bodyParser())}}?", 8 | "14b06036ad206e2b038840c24e677b4d": "Funkcja {{OAuth2orize}} wymaga obsługi transakcji. Czy zapomniano o metodzie {{oauth2orize.transactionLoader(...)}}?", 9 | "19d7beb3c393b20162c2c43135b4f1c0": "Kod autoryzacji utracił ważność", 10 | "1e1b2073df0a8963670e9ed1e181dfe8": "Niepoprawny element {{JWT}}: {0}", 11 | "24ff616d05fe6b8dca8859d9dafa729e": "Niepoprawny klient", 12 | "2caa676b18561101c92e69d70820b1bf": "Funkcja {{OAuth2orize}} wymaga obsługi właściwości {{session}}. Czy zapomniano o metodzie {{app.use(express.session(...))}}?", 13 | "37086a106da98d5322d134d7905d1817": "Brak wymaganego parametru: {{code}}", 14 | "373b2ad70311b6537ad42719088da022": "Deserializacja klienta nie powiodła się. Zarejestruj funkcję deserializacji przy użyciu metody {{deserializeClient()}}.", 15 | "3bffb3bbef4312d6bcbabd3240e79ef2": "Nadanie {{oauth2orize.code}} wymaga wywołania zwrotnego {{issue}}", 16 | "3cfcae051965e0da5f704a334e1e884c": "Niezgodność identyfikatora klienta", 17 | "43a5b5bf0c7dd0bf5fec2601fe347245": "Niepoprawne żądanie: brak elementu {{redirect_uri}}", 18 | "4428b355c8ba3e248b8fc0857e2181a0": "Nieobsługiwany typ nadania: {0}", 19 | "452b7bd4aed1b69b7c20fb701377c4eb": "Nieautoryzowany element {{redirectURI}}: {0}", 20 | "47db77dd8ab3aa3c3ec1e6c955c0cc01": "Brak wymaganego parametru: {{username}}", 21 | "53c21d3a92686e2956d527d097e1e1b9": "Znacznik dostępu ma niepoprawny identyfikator {{user id}}: {0}", 22 | "54d8df1f46d3358dd33ba274a537b519": "Nieobsługiwany typ znacznika: {0}", 23 | "5b853ac61fab20ec62d53e183e067ec3": "Serializacja klienta nie powiodła się. Zarejestruj funkcję serializacji przy użyciu metody {{serializeClient()}}.", 24 | "5bc4d117f87ba20efb8cdd4c988ed46d": "Warstwa pośrednia {{oauth2orize.transactionLoader}} wymaga argumentu {{server}}", 25 | "6d3b5c2b2c7c20cd8907a0b090f0e89c": "Niepoprawny znacznik odświeżania", 26 | "6e0122e493bd949f408c1421fc757b95": "Nie można wykonać przekierowania dla transakcji {{OAuth 2.0}}", 27 | "7175ea69be895be338ca9f9168268dab": "Warstwa pośrednia {{oauth2orize.decision}} wymaga argumentu {{server}}", 28 | "740f3fb2bd1358d65943e735224d23e5": "Brak wymaganego parametru: {{refresh_token}}", 29 | "76d075ea0325d32667fad67c446e469b": "niepoprawny element {{JWT}}", 30 | "8000aa2c64d9c95c406053764fc33f64": "Nieautoryzowany klient", 31 | "83459aaa8e2d81c7fad2b899ad0cbf57": "Komponent {{OAuth2}} nie został skonfigurowany dla tej aplikacji.", 32 | "839544ec984d6290cd45669efdd39699": "Niezgodność przekierowania {{uri}}", 33 | "8782860f8d60f2bdb6f67d623dd7e51f": "Warstwa pośrednia {{oauth2orize.authorization}} wymaga funkcji {{validate}}", 34 | "9508d060bc6fd6e25cb4d0c00ea0480d": "Niewystarczający zasięg", 35 | "a198c4335c42739230d7d8afacdc109d": "Warstwa pośrednia wymiany {{OAuth 2.0 jwtBearer}} wymaga funkcji {{issue}}.", 36 | "a23d7ec09a60c8bbd119d8287d8b5805": "Warstwa pośrednia {{oauth2orize.revoke}} wymaga funkcji {{revokeToken}}", 37 | "a2f3ad97b7b05618b6722b8f07e9f805": "Strategia posiadacza {{OAuth 2.0 JWT}} wymaga wywołania zwrotnego weryfikacji", 38 | "a7b39a5a13fdba4772a83e07cb864156": "Nie można załadować transakcji {{OAuth 2.0}} z sesji", 39 | "a82c6b0f0db10b6e198e99068e765570": "Strategia posiadacza {{OAuth 2.0 JWT}} wymaga opcji grupy docelowej", 40 | "aaee2c79ab90ccc63b9d46795e19620a": "Wymiana {{oauth2orize.clientCredentials}} wymaga wywołania zwrotnego wydania", 41 | "ae02475e560f64afdcf6d02bc80dcb0e": "Niepoprawne referencje klienta", 42 | "b1af8f34c3d25bd59189205046665bfd": "Brak wymaganego parametru: {0}", 43 | "b1eb21b6d32dde679f9b4bf0b2e0939d": "Strategia {{MACStrategy}} wymaga wywołania zwrotnego weryfikacji", 44 | "bac74f7415259e303903cfc8a7bcc4df": "Warstwa pośrednia {{oauth2orize.token}} wymaga argumentu {{server}}", 45 | "bcb1c003530e6fb715ad605ea7fe83d9": "Nadanie {{oauth2orize.token}} wymaga wywołania zwrotnego {{issue}}", 46 | "cbd12265f4ab78b30a0977e37aefcf37": "Brak wymaganego parametru: {{password}}", 47 | "cdee717bf439af4c84eabb54b82c13af": "Wymiana {{oauth2orize.authorizationCode}} wymaga wywołania zwrotnego wydania", 48 | "d36b1a9f8719a56a091ed6c89d3cd1fa": "Żądanie odrzucone przez serwer autoryzacji", 49 | "d3dd8b2220bba70a6e7e44af24a4157c": "Brak wymaganego parametru: {{token}}", 50 | "d837f7c0309bf4816cbbb22b57473733": "Wymiana {{oauth2orize.password}} wymaga wywołania zwrotnego {{issue}}", 51 | "d83b55a5dfd3e16ca22699e39b072f3f": "Znacznik dostępu ma niepoprawny identyfikator {{app id}}: {0}", 52 | "db8b02ad229f45cbb12e0d9845b09eb2": "Strategia posiadacza {{OAuth 2.0 JWT}} wymaga wywołania zwrotnego kluczy", 53 | "e173a3cecca19bcbf528408adc001750": "Nieautoryzowany typ odpowiedzi: {0}", 54 | "e82c91e82424949d4390135e5e8adf1c": "Niepoprawny znacznik {{MAC}}", 55 | "eb30f051fcf0e7338bf4d8489f583378": "Nieautoryzowany element {{scope}}: {0}", 56 | "ec30fea412580b611d7a274ee1163e5c": "Brak wymaganego parametru: {{response_type}}", 57 | "ec9ddf242c3da3b5cf44def6398706ec": "Wymiana {{oauth2orize.refreshToken}} wymaga wywołania zwrotnego {{issue}}", 58 | "ed5c8e0055b1cae433e4c393ae04d555": "Niepoprawne elementy: {0}", 59 | "f06abf2e08aba65a62f4486bc2418413": "Warstwa pośrednia {{oauth2orize.revoke}} wymaga argumentu {{server}}", 60 | "f24b75ecdc45edb84b0c9fec3b6f1e5b": "Nie można załadować transakcji {{OAuth 2.0}}: {0}", 61 | "f483b2bebd08d285c7009c6812f5ba24": "Znacznik dostępu utracił ważność", 62 | "f50708df489d7811db692c0b601483f8": "Brak wymaganego parametru: {{client_id}}", 63 | "fa925eb4771bd2897f14b1de78ca0ed2": "Niepoprawny podmiot: {0}", 64 | "fcdd5cf7956698312e899ddb708abbaf": "brak parametru asercji", 65 | "fef19f407c562658e0132f1625ce968b": "Nieautoryzowany typ nadania: {0}", 66 | "ff7883d90a5fe850e026885759165406": "Niepoprawne referencje właściciela zasobu" 67 | } 68 | 69 | -------------------------------------------------------------------------------- /intl/pt/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "06f6133efc10bf1f9a2c6b5161c66fba": "Corpo da solicitação não analisado. Use o middleware do {{bodyParser}}.", 3 | "083123c0a745a514ce06fa527c151a46": "Middleware de {{oauth2orize.authorization}} requer um argumento de {{server}}", 4 | "092f3dd9c9bde61eed97f67459b46a7e": "Tipo de resposta não suportado: {0}", 5 | "102a3213ff01fc1b03faa5cbe720e6c0": "Código de autorização inválido", 6 | "10b283f781f47e879e25e3b3b84f85e3": "Permissão negada por {0}", 7 | "12df3715215d39fdb1c5c19775091f31": "{{OAuth2orize}} requer análise sintática do corpo. Você se esqueceu de {{app.use(express.bodyParser())}}?", 8 | "14b06036ad206e2b038840c24e677b4d": "{{OAuth2orize}} requer suporte a transações. Você se esqueceu de {{oauth2orize.transactionLoader(...)}}?", 9 | "19d7beb3c393b20162c2c43135b4f1c0": "Código de autorização está expirado", 10 | "1e1b2073df0a8963670e9ed1e181dfe8": "{{JWT}} inválido: {0}", 11 | "24ff616d05fe6b8dca8859d9dafa729e": "Cliente inválido", 12 | "2caa676b18561101c92e69d70820b1bf": "{{OAuth2orize}} requer suporte de {{session}}. Você se esqueceu de {{app.use(express.session(...))}}?", 13 | "37086a106da98d5322d134d7905d1817": "Parâmetro necessário ausente: {{code}}", 14 | "373b2ad70311b6537ad42719088da022": "Falha ao desserializar cliente. Registre a função de desserialização usando {{deserializeClient()}}.", 15 | "3bffb3bbef4312d6bcbabd3240e79ef2": "Concessão de {{oauth2orize.code}} requer um retorno de chamada de {{issue}}", 16 | "3cfcae051965e0da5f704a334e1e884c": "Incompatibilidades de ID do cliente", 17 | "43a5b5bf0c7dd0bf5fec2601fe347245": "Solicitação inválida: {{redirect_uri}} está ausente", 18 | "4428b355c8ba3e248b8fc0857e2181a0": "Tipo de concessão não suportado: {0}", 19 | "452b7bd4aed1b69b7c20fb701377c4eb": "{{redirectURI}} desautorizado: {0}", 20 | "47db77dd8ab3aa3c3ec1e6c955c0cc01": "Parâmetro necessário ausente: {{username}}", 21 | "53c21d3a92686e2956d527d097e1e1b9": "Token de acesso possui {{user id}} inválido: {0}", 22 | "54d8df1f46d3358dd33ba274a537b519": "Tipo de token não suportado: {0}", 23 | "5b853ac61fab20ec62d53e183e067ec3": "Falha ao serializar cliente. Registre a função de serialização usando {{serializeClient()}}.", 24 | "5bc4d117f87ba20efb8cdd4c988ed46d": "Middleware de {{oauth2orize.transactionLoader}} requer um argumento de {{server}}", 25 | "6d3b5c2b2c7c20cd8907a0b090f0e89c": "Token de atualização inválido", 26 | "6e0122e493bd949f408c1421fc757b95": "Não é possível emitir redirecionamento para transação de {{OAuth 2.0}}", 27 | "7175ea69be895be338ca9f9168268dab": "Middleware de {{oauth2orize.decision}} requer um argumento de {{server}}", 28 | "740f3fb2bd1358d65943e735224d23e5": "Parâmetro necessário ausente: {{refresh_token}}", 29 | "76d075ea0325d32667fad67c446e469b": "{{JWT}} inválido", 30 | "8000aa2c64d9c95c406053764fc33f64": "Cliente desautorizado", 31 | "83459aaa8e2d81c7fad2b899ad0cbf57": "O componente {{OAuth2}} não foi configurado para este aplicativo.", 32 | "839544ec984d6290cd45669efdd39699": "Redirecionar incompatibilidades de {{uri}}", 33 | "8782860f8d60f2bdb6f67d623dd7e51f": "Middleware de {{oauth2orize.authorization}} requer uma função {{validate}}", 34 | "9508d060bc6fd6e25cb4d0c00ea0480d": "Escopo insuficiente", 35 | "a198c4335c42739230d7d8afacdc109d": "Middleware de troca de {{OAuth 2.0 jwtBearer}} requer uma função {{issue}}.", 36 | "a23d7ec09a60c8bbd119d8287d8b5805": "Middleware de {{oauth2orize.revoke}} requer uma função {{revokeToken}}", 37 | "a2f3ad97b7b05618b6722b8f07e9f805": "Estratégia do portador {{OAuth 2.0 JWT}} requer um retorno de chamada de verificação", 38 | "a7b39a5a13fdba4772a83e07cb864156": "Não é possível carregar transações de {{OAuth 2.0}} a partir da sessão", 39 | "a82c6b0f0db10b6e198e99068e765570": "Estratégia do portador {{OAuth 2.0 JWT}} requer uma opção de público", 40 | "aaee2c79ab90ccc63b9d46795e19620a": "Troca de {{oauth2orize.clientCredentials}} requer um retorno de chamada de emissão", 41 | "ae02475e560f64afdcf6d02bc80dcb0e": "Credenciais do cliente inválidas", 42 | "b1af8f34c3d25bd59189205046665bfd": "Parâmetro obrigatório ausente: {0}", 43 | "b1eb21b6d32dde679f9b4bf0b2e0939d": "{{MACStrategy}} requer um retorno de chamada de verificação", 44 | "bac74f7415259e303903cfc8a7bcc4df": "Middleware de {{oauth2orize.token}} requer um argumento de {{server}}", 45 | "bcb1c003530e6fb715ad605ea7fe83d9": "Concessão de {{oauth2orize.token}} requer um retorno de chamada de {{issue}}", 46 | "cbd12265f4ab78b30a0977e37aefcf37": "Parâmetro necessário ausente: {{password}}", 47 | "cdee717bf439af4c84eabb54b82c13af": "Troca de {{oauth2orize.authorizationCode}} requer um retorno de chamada de emissão", 48 | "d36b1a9f8719a56a091ed6c89d3cd1fa": "Solicitação negada pelo servidor de autorização", 49 | "d3dd8b2220bba70a6e7e44af24a4157c": "Parâmetro necessário ausente: {{token}}", 50 | "d837f7c0309bf4816cbbb22b57473733": "Troca de {{oauth2orize.password}} requer um retorno de chamada de {{issue}}", 51 | "d83b55a5dfd3e16ca22699e39b072f3f": "Token de acesso possui {{app id}} inválido: {0}", 52 | "db8b02ad229f45cbb12e0d9845b09eb2": "Estratégia do portador {{OAuth 2.0 JWT}} requer um retorno de chamada de chaveamento", 53 | "e173a3cecca19bcbf528408adc001750": "Tipo de resposta desautorizado: {0}", 54 | "e82c91e82424949d4390135e5e8adf1c": "Token {{MAC}} inválido", 55 | "eb30f051fcf0e7338bf4d8489f583378": "{{scope}} desautorizado: {0}", 56 | "ec30fea412580b611d7a274ee1163e5c": "Parâmetro necessário ausente: {{response_type}}", 57 | "ec9ddf242c3da3b5cf44def6398706ec": "Troca de {{oauth2orize.refreshToken}} requer um retorno de chamada de {{issue}}", 58 | "ed5c8e0055b1cae433e4c393ae04d555": "Itens inválidos: {0}", 59 | "f06abf2e08aba65a62f4486bc2418413": "Middleware de {{oauth2orize.revoke}} requer um argumento de {{server}}", 60 | "f24b75ecdc45edb84b0c9fec3b6f1e5b": "Não é possível carregar transação de {{OAuth 2.0}}: {0}", 61 | "f483b2bebd08d285c7009c6812f5ba24": "O token de acesso está expirado", 62 | "f50708df489d7811db692c0b601483f8": "Parâmetro necessário ausente: {{client_id}}", 63 | "fa925eb4771bd2897f14b1de78ca0ed2": "Assunto inválido: {0}", 64 | "fcdd5cf7956698312e899ddb708abbaf": "parâmetro de asserção ausente", 65 | "fef19f407c562658e0132f1625ce968b": "Tipo de concessão desautorizado: {0}", 66 | "ff7883d90a5fe850e026885759165406": "Credenciais do proprietário do recurso inválidas" 67 | } 68 | 69 | -------------------------------------------------------------------------------- /intl/tr/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "06f6133efc10bf1f9a2c6b5161c66fba": "İstek gövdesi ayrıştırılamadı. {{bodyParser}} ara katman yazılımını kullanın.", 3 | "083123c0a745a514ce06fa527c151a46": "{{oauth2orize.authorization}} ara katman yazılımı bir {{server}} bağımsız değişkenini gerektirir", 4 | "092f3dd9c9bde61eed97f67459b46a7e": "Desteklenmeyen yanıt tipi: {0}", 5 | "102a3213ff01fc1b03faa5cbe720e6c0": "Yetkilendirme kodu geçersiz", 6 | "10b283f781f47e879e25e3b3b84f85e3": "İzin {0} tarafından reddedildi", 7 | "12df3715215d39fdb1c5c19775091f31": "{{OAuth2orize}} için gövde ayrıştırması gerekli. {{app.use(express.bodyParser())}} belirtmeyi unuttunuz mu?", 8 | "14b06036ad206e2b038840c24e677b4d": "{{OAuth2orize}} işlem desteği gerektirir. {{oauth2orize.transactionLoader(...)}} belirtmeyi unuttunuz mu?", 9 | "19d7beb3c393b20162c2c43135b4f1c0": "Yetkilendirme kodunun süresi doldu", 10 | "1e1b2073df0a8963670e9ed1e181dfe8": "Geçersiz {{JWT}}: {0}", 11 | "24ff616d05fe6b8dca8859d9dafa729e": "Geçersiz istemci", 12 | "2caa676b18561101c92e69d70820b1bf": "{{OAuth2orize}}, {{session}} desteği gerektirir. {{app.use(express.session(...))}} belirtmeyi unuttunuz mu?", 13 | "37086a106da98d5322d134d7905d1817": "Zorunlu parametre eksik: {{code}}", 14 | "373b2ad70311b6537ad42719088da022": "İstemci serileştirilmiş durumdan geri çevrilemedi. Serileşmeyi kaldırma işlevini {{deserializeClient()}} ile kaydettirin.", 15 | "3bffb3bbef4312d6bcbabd3240e79ef2": "{{oauth2orize.code}} verilmesi bir {{issue}} geri çağrısını gerektirir", 16 | "3cfcae051965e0da5f704a334e1e884c": "İstemci tanıtıcısı uyuşmazlığı", 17 | "43a5b5bf0c7dd0bf5fec2601fe347245": "Geçersiz istek: {{redirect_uri}} eksik", 18 | "4428b355c8ba3e248b8fc0857e2181a0": "Desteklenmeyen verme tipi: {0}", 19 | "452b7bd4aed1b69b7c20fb701377c4eb": "Yetkisiz {{redirectURI}}: {0}", 20 | "47db77dd8ab3aa3c3ec1e6c955c0cc01": "Zorunlu parametre eksik: {{username}}", 21 | "53c21d3a92686e2956d527d097e1e1b9": "Erişim belirtecinde {{user id}} geçersiz: {0}", 22 | "54d8df1f46d3358dd33ba274a537b519": "Desteklenmeyen belirteç tipi: {0}", 23 | "5b853ac61fab20ec62d53e183e067ec3": "İstemci serileştirilemedi. Serileştirme işlevini {{serializeClient()}} ile kaydettirin.", 24 | "5bc4d117f87ba20efb8cdd4c988ed46d": "{{oauth2orize.transactionLoader}} ara katman yazılımı bir {{server}} bağımsız değişkenini gerektirir", 25 | "6d3b5c2b2c7c20cd8907a0b090f0e89c": "Yenileme belirteci geçersiz", 26 | "6e0122e493bd949f408c1421fc757b95": "{{OAuth 2.0}} işlemi için yeniden yönlendirme yayınlanamıyor", 27 | "7175ea69be895be338ca9f9168268dab": "{{oauth2orize.decision}} ara katman yazılımı bir {{server}} bağımsız değişkenini gerektirir", 28 | "740f3fb2bd1358d65943e735224d23e5": "Zorunlu parametre eksik: {{refresh_token}}", 29 | "76d075ea0325d32667fad67c446e469b": "geçersiz {{JWT}}", 30 | "8000aa2c64d9c95c406053764fc33f64": "Yetkisiz istemci", 31 | "83459aaa8e2d81c7fad2b899ad0cbf57": "Bu uygulama için {{OAuth2}} bileşeni yapılandırılmadı.", 32 | "839544ec984d6290cd45669efdd39699": "Yeniden yönlendirme {{uri}} uyuşmazlığı", 33 | "8782860f8d60f2bdb6f67d623dd7e51f": "{{oauth2orize.authorization}} ara katman yazılımı bir {{validate}} işlevini gerektirir", 34 | "9508d060bc6fd6e25cb4d0c00ea0480d": "Yetersiz kapsam", 35 | "a198c4335c42739230d7d8afacdc109d": "{{OAuth 2.0 jwtBearer}} değişim ara katman yazılımı bir {{issue}} işlevini gerektirir.", 36 | "a23d7ec09a60c8bbd119d8287d8b5805": "{{oauth2orize.revoke}} ara katman yazılımı bir {{revokeToken}} işlevini gerektirir", 37 | "a2f3ad97b7b05618b6722b8f07e9f805": "{{OAuth 2.0 JWT}} taşıyıcı stratejisi bir doğrulama geri çağrısı gerektirir", 38 | "a7b39a5a13fdba4772a83e07cb864156": "Oturumdan {{OAuth 2.0}} işlemleri yüklenemiyor", 39 | "a82c6b0f0db10b6e198e99068e765570": "{{OAuth 2.0 JWT}} taşıyıcı stratejisi bir hedef kitle seçeneği gerektirir", 40 | "aaee2c79ab90ccc63b9d46795e19620a": "{{oauth2orize.clientCredentials}} değişimi bir sorun geri çağrısını gerektirir", 41 | "ae02475e560f64afdcf6d02bc80dcb0e": "İstemci kimlik bilgileri geçersiz", 42 | "b1af8f34c3d25bd59189205046665bfd": "Zorunlu parametre eksik: {0}", 43 | "b1eb21b6d32dde679f9b4bf0b2e0939d": "{{MACStrategy}} bir doğrulama geri çağrısı gerektirir", 44 | "bac74f7415259e303903cfc8a7bcc4df": "{{oauth2orize.token}} ara katman yazılımı bir {{server}} bağımsız değişkenini gerektirir", 45 | "bcb1c003530e6fb715ad605ea7fe83d9": "{{oauth2orize.token}} verilmesi bir {{issue}} geri çağrısını gerektirir", 46 | "cbd12265f4ab78b30a0977e37aefcf37": "Zorunlu parametre eksik: {{password}}", 47 | "cdee717bf439af4c84eabb54b82c13af": "{{oauth2orize.authorizationCode}} değişimi bir sorun geri çağrısını gerektirir", 48 | "d36b1a9f8719a56a091ed6c89d3cd1fa": "Yetkilendirme sunucusu isteği reddetti", 49 | "d3dd8b2220bba70a6e7e44af24a4157c": "Zorunlu parametre eksik: {{token}}", 50 | "d837f7c0309bf4816cbbb22b57473733": "{{oauth2orize.password}} değişimi bir {{issue}} geri çağrısını gerektirir", 51 | "d83b55a5dfd3e16ca22699e39b072f3f": "Erişim belirtecinde {{app id}} geçersiz: {0}", 52 | "db8b02ad229f45cbb12e0d9845b09eb2": "{{OAuth 2.0 JWT}} taşıyıcı stratejisi bir giriş geri çağrısı gerektirir", 53 | "e173a3cecca19bcbf528408adc001750": "Yetkisiz yanıt tipi: {0}", 54 | "e82c91e82424949d4390135e5e8adf1c": "Geçersiz {{MAC}} belirteci", 55 | "eb30f051fcf0e7338bf4d8489f583378": "Yetkisiz {{scope}}: {0}", 56 | "ec30fea412580b611d7a274ee1163e5c": "Zorunlu parametre eksik: {{response_type}}", 57 | "ec9ddf242c3da3b5cf44def6398706ec": "{{oauth2orize.refreshToken}} değişimi bir {{issue}} geri çağrısını gerektirir", 58 | "ed5c8e0055b1cae433e4c393ae04d555": "Geçersiz öğeler: {0}", 59 | "f06abf2e08aba65a62f4486bc2418413": "{{oauth2orize.revoke}} ara katman yazılımı bir {{server}} bağımsız değişkenini gerektirir", 60 | "f24b75ecdc45edb84b0c9fec3b6f1e5b": "{{OAuth 2.0}} işlemi yüklenemiyor: {0}", 61 | "f483b2bebd08d285c7009c6812f5ba24": "Etişim belirtecinin süresi doldu", 62 | "f50708df489d7811db692c0b601483f8": "Zorunlu parametre eksik: {{client_id}}", 63 | "fa925eb4771bd2897f14b1de78ca0ed2": "Geçersiz konu: {0}", 64 | "fcdd5cf7956698312e899ddb708abbaf": "değerlendirme parametresi eksik", 65 | "fef19f407c562658e0132f1625ce968b": "Yetkisiz verme tipi: {0}", 66 | "ff7883d90a5fe850e026885759165406": "Kaynak sahibinin kimlik bilgileri geçersiz" 67 | } 68 | 69 | -------------------------------------------------------------------------------- /intl/zh-Hans/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "06f6133efc10bf1f9a2c6b5161c66fba": "未解析请求主体。使用 {{bodyParser}} 中间件。", 3 | "083123c0a745a514ce06fa527c151a46": "{{oauth2orize.authorization}} 中间件需要 {{server}} 自变量", 4 | "092f3dd9c9bde61eed97f67459b46a7e": "不受支持的响应类型:{0}", 5 | "102a3213ff01fc1b03faa5cbe720e6c0": "无效的授权代码", 6 | "10b283f781f47e879e25e3b3b84f85e3": "{0} 拒绝许可权", 7 | "12df3715215d39fdb1c5c19775091f31": "{{OAuth2orize}} 需要主体解析。是否忘记 {{app.use(express.bodyParser())}}?", 8 | "14b06036ad206e2b038840c24e677b4d": "{{OAuth2orize}} 需要事务支持。是否忘记 {{oauth2orize.transactionLoader(...)}}?", 9 | "19d7beb3c393b20162c2c43135b4f1c0": "授权代码已到期", 10 | "1e1b2073df0a8963670e9ed1e181dfe8": "无效的 {{JWT}}:{0}", 11 | "24ff616d05fe6b8dca8859d9dafa729e": "无效的客户机", 12 | "2caa676b18561101c92e69d70820b1bf": "{{OAuth2orize}} 需要 {{session}} 支持。是否忘记 {{app.use(express.session(...))}}?", 13 | "37086a106da98d5322d134d7905d1817": "缺少必需参数:{{code}}", 14 | "373b2ad70311b6537ad42719088da022": "无法反序列化客户机。使用 {{deserializeClient()}} 注册反序列化函数。", 15 | "3bffb3bbef4312d6bcbabd3240e79ef2": "{{oauth2orize.code}} 授权需要 {{issue}} 回调", 16 | "3cfcae051965e0da5f704a334e1e884c": "客户机标识不匹配", 17 | "43a5b5bf0c7dd0bf5fec2601fe347245": "无效的请求:缺少 {{redirect_uri}}", 18 | "4428b355c8ba3e248b8fc0857e2181a0": "不受支持的授权类型:{0}", 19 | "452b7bd4aed1b69b7c20fb701377c4eb": "未经授权的 {{redirectURI}}:{0}", 20 | "47db77dd8ab3aa3c3ec1e6c955c0cc01": "缺少必需参数:{{username}}", 21 | "53c21d3a92686e2956d527d097e1e1b9": "访问令牌包含无效的 {{user id}}:{0}", 22 | "54d8df1f46d3358dd33ba274a537b519": "不受支持的令牌类型:{0}", 23 | "5b853ac61fab20ec62d53e183e067ec3": "无法序列化客户机。使用 {{serializeClient()}} 注册序列化函数。", 24 | "5bc4d117f87ba20efb8cdd4c988ed46d": "{{oauth2orize.transactionLoader}} 中间件需要 {{server}} 自变量", 25 | "6d3b5c2b2c7c20cd8907a0b090f0e89c": "无效的刷新令牌", 26 | "6e0122e493bd949f408c1421fc757b95": "无法针对 {{OAuth 2.0}} 事务发出重定向", 27 | "7175ea69be895be338ca9f9168268dab": "{{oauth2orize.decision}} 中间件需要 {{server}} 自变量", 28 | "740f3fb2bd1358d65943e735224d23e5": "缺少必需参数:{{refresh_token}}", 29 | "76d075ea0325d32667fad67c446e469b": "无效的 {{JWT}}", 30 | "8000aa2c64d9c95c406053764fc33f64": "未经授权的客户机", 31 | "83459aaa8e2d81c7fad2b899ad0cbf57": "未针对此应用程序配置 {{OAuth2}} 组件。", 32 | "839544ec984d6290cd45669efdd39699": "重定向 {{uri}} 不匹配", 33 | "8782860f8d60f2bdb6f67d623dd7e51f": "{{oauth2orize.authorization}} 中间件需要 {{validate}} 函数", 34 | "9508d060bc6fd6e25cb4d0c00ea0480d": "作用域不足", 35 | "a198c4335c42739230d7d8afacdc109d": "{{OAuth 2.0 jwtBearer}} 交换中间件需要 {{issue}} 函数", 36 | "a23d7ec09a60c8bbd119d8287d8b5805": "{{oauth2orize.revoke}} 中间件需要 {{revokeToken}} 函数", 37 | "a2f3ad97b7b05618b6722b8f07e9f805": "{{OAuth 2.0 JWT}} 持有者策略需要验证回调", 38 | "a7b39a5a13fdba4772a83e07cb864156": "无法从会话装入 {{OAuth 2.0}} 事务", 39 | "a82c6b0f0db10b6e198e99068e765570": "{{OAuth 2.0 JWT}} 持有者策略需要受众选项", 40 | "aaee2c79ab90ccc63b9d46795e19620a": "{{oauth2orize.clientCredentials}} 交换需要问题回调", 41 | "ae02475e560f64afdcf6d02bc80dcb0e": "无效的客户机凭证", 42 | "b1af8f34c3d25bd59189205046665bfd": "缺少必需参数:{0}", 43 | "b1eb21b6d32dde679f9b4bf0b2e0939d": "{{MACStrategy}} 需要验证回调", 44 | "bac74f7415259e303903cfc8a7bcc4df": "{{oauth2orize.token}} 中间件需要 {{server}} 自变量", 45 | "bcb1c003530e6fb715ad605ea7fe83d9": "{{oauth2orize.token}} 授权需要 {{issue}} 回调", 46 | "cbd12265f4ab78b30a0977e37aefcf37": "缺少必需参数:{{password}}", 47 | "cdee717bf439af4c84eabb54b82c13af": "{{oauth2orize.authorizationCode}} 交换需要问题回调", 48 | "d36b1a9f8719a56a091ed6c89d3cd1fa": "授权服务器拒绝请求", 49 | "d3dd8b2220bba70a6e7e44af24a4157c": "缺少必需参数:{{token}}", 50 | "d837f7c0309bf4816cbbb22b57473733": "{{oauth2orize.password}} 交换需要 {{issue}} 回调", 51 | "d83b55a5dfd3e16ca22699e39b072f3f": "访问令牌包含无效的 {{app id}}:{0}", 52 | "db8b02ad229f45cbb12e0d9845b09eb2": "{{OAuth 2.0 JWT}} 持有者策略需要键控回调", 53 | "e173a3cecca19bcbf528408adc001750": "未经授权的响应类型:{0}", 54 | "e82c91e82424949d4390135e5e8adf1c": "无效的 {{MAC}} 令牌", 55 | "eb30f051fcf0e7338bf4d8489f583378": "未经授权的 {{scope}}:{0}", 56 | "ec30fea412580b611d7a274ee1163e5c": "缺少必需参数:{{response_type}}", 57 | "ec9ddf242c3da3b5cf44def6398706ec": "{{oauth2orize.refreshToken}} 交换需要 {{issue}} 回调", 58 | "ed5c8e0055b1cae433e4c393ae04d555": "无效项:{0}", 59 | "f06abf2e08aba65a62f4486bc2418413": "{{oauth2orize.revoke}} 中间件需要 {{server}} 自变量", 60 | "f24b75ecdc45edb84b0c9fec3b6f1e5b": "无法装入 {{OAuth 2.0}} 事务:{0}", 61 | "f483b2bebd08d285c7009c6812f5ba24": "访问令牌到期", 62 | "f50708df489d7811db692c0b601483f8": "缺少必需参数:{{client_id}}", 63 | "fa925eb4771bd2897f14b1de78ca0ed2": "无效的主题:{0}", 64 | "fcdd5cf7956698312e899ddb708abbaf": "缺少断言参数", 65 | "fef19f407c562658e0132f1625ce968b": "未经授权的授权类型:{0}", 66 | "ff7883d90a5fe850e026885759165406": "无效的资源所有者凭证" 67 | } 68 | 69 | -------------------------------------------------------------------------------- /intl/zh-Hant/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "06f6133efc10bf1f9a2c6b5161c66fba": "未剖析要求內文。請使用 {{bodyParser}} 中介軟體。", 3 | "083123c0a745a514ce06fa527c151a46": "{{oauth2orize.authorization}} 中介軟體需要 {{server}} 引數", 4 | "092f3dd9c9bde61eed97f67459b46a7e": "不受支援的回應類型:{0}", 5 | "102a3213ff01fc1b03faa5cbe720e6c0": "授權碼無效", 6 | "10b283f781f47e879e25e3b3b84f85e3": "{0} 拒絕許可權", 7 | "12df3715215d39fdb1c5c19775091f31": "{{OAuth2orize}} 需要內文剖析。您是否忘記 {{app.use(express.bodyParser())}}?", 8 | "14b06036ad206e2b038840c24e677b4d": "{{OAuth2orize}} 需要交易支援。您是否忘記 {{oauth2orize.transactionLoader(...)}}?", 9 | "19d7beb3c393b20162c2c43135b4f1c0": "授權碼過期", 10 | "1e1b2073df0a8963670e9ed1e181dfe8": "無效 {{JWT}}:{0}", 11 | "24ff616d05fe6b8dca8859d9dafa729e": "用戶端無效", 12 | "2caa676b18561101c92e69d70820b1bf": "{{OAuth2orize}} 需要 {{session}} 支援。您是否忘記 {{app.use(express.session(...))}}?", 13 | "37086a106da98d5322d134d7905d1817": "遺漏必要的參數:{{code}}", 14 | "373b2ad70311b6537ad42719088da022": "無法將用戶端解除序列化。請使用 {{deserializeClient()}} 來登錄解除序列化函數。", 15 | "3bffb3bbef4312d6bcbabd3240e79ef2": "{{oauth2orize.code}} 授權需要 {{issue}} 回呼", 16 | "3cfcae051965e0da5f704a334e1e884c": "用戶端 id 不符", 17 | "43a5b5bf0c7dd0bf5fec2601fe347245": "無效要求:遺漏 {{redirect_uri}}", 18 | "4428b355c8ba3e248b8fc0857e2181a0": "不受支援的授權類型:{0}", 19 | "452b7bd4aed1b69b7c20fb701377c4eb": "未獲授權的 {{redirectURI}}:{0}", 20 | "47db77dd8ab3aa3c3ec1e6c955c0cc01": "遺漏必要的參數:{{username}}", 21 | "53c21d3a92686e2956d527d097e1e1b9": "存取記號的 {{user id}} 無效:{0}", 22 | "54d8df1f46d3358dd33ba274a537b519": "不受支援的記號類型:{0}", 23 | "5b853ac61fab20ec62d53e183e067ec3": "無法將用戶端序列化。請使用 {{serializeClient()}} 來登錄序列化函數。", 24 | "5bc4d117f87ba20efb8cdd4c988ed46d": "{{oauth2orize.transactionLoader}} 中介軟體需要 {{server}} 引數", 25 | "6d3b5c2b2c7c20cd8907a0b090f0e89c": "重新整理記號無效", 26 | "6e0122e493bd949f408c1421fc757b95": "無法為 {{OAuth 2.0}} 交易發出重新導向", 27 | "7175ea69be895be338ca9f9168268dab": "{{oauth2orize.decision}} 中介軟體需要 {{server}} 引數", 28 | "740f3fb2bd1358d65943e735224d23e5": "遺漏必要的參數:{{refresh_token}}", 29 | "76d075ea0325d32667fad67c446e469b": "{{JWT}} 無效", 30 | "8000aa2c64d9c95c406053764fc33f64": "未獲授權的用戶端", 31 | "83459aaa8e2d81c7fad2b899ad0cbf57": "未配置這個應用程式的 {{OAuth2}} 元件。", 32 | "839544ec984d6290cd45669efdd39699": "重新導向 {{uri}} 不符", 33 | "8782860f8d60f2bdb6f67d623dd7e51f": "{{oauth2orize.authorization}} 中介軟體需要 {{validate}} 函數", 34 | "9508d060bc6fd6e25cb4d0c00ea0480d": "範圍不足", 35 | "a198c4335c42739230d7d8afacdc109d": "{{OAuth 2.0 jwtBearer}} 交換中介軟體需要 {{issue}} 函數。", 36 | "a23d7ec09a60c8bbd119d8287d8b5805": "{{oauth2orize.revoke}} 中介軟體需要 {{revokeToken}} 函數", 37 | "a2f3ad97b7b05618b6722b8f07e9f805": "{{OAuth 2.0 JWT}} 載送者策略需要 verify 回呼", 38 | "a7b39a5a13fdba4772a83e07cb864156": "無法從階段作業載入 {{OAuth 2.0}} 交易", 39 | "a82c6b0f0db10b6e198e99068e765570": "{{OAuth 2.0 JWT}} 載送者策略需要 audience 選項", 40 | "aaee2c79ab90ccc63b9d46795e19620a": "{{oauth2orize.clientCredentials}} 交換需要 issue 回呼", 41 | "ae02475e560f64afdcf6d02bc80dcb0e": "用戶端認證無效", 42 | "b1af8f34c3d25bd59189205046665bfd": "遺漏必要的參數:{0}", 43 | "b1eb21b6d32dde679f9b4bf0b2e0939d": "{{MACStrategy}} 需要 verify 回呼", 44 | "bac74f7415259e303903cfc8a7bcc4df": "{{oauth2orize.token}} 中介軟體需要 {{server}} 引數", 45 | "bcb1c003530e6fb715ad605ea7fe83d9": "{{oauth2orize.token}} 授權需要 {{issue}} 回呼", 46 | "cbd12265f4ab78b30a0977e37aefcf37": "遺漏必要的參數:{{password}}", 47 | "cdee717bf439af4c84eabb54b82c13af": "{{oauth2orize.authorizationCode}} 交換需要 issue 回呼", 48 | "d36b1a9f8719a56a091ed6c89d3cd1fa": "授權伺服器拒絕要求", 49 | "d3dd8b2220bba70a6e7e44af24a4157c": "遺漏必要的參數:{{token}}", 50 | "d837f7c0309bf4816cbbb22b57473733": "{{oauth2orize.password}} 交換需要 {{issue}} 回呼", 51 | "d83b55a5dfd3e16ca22699e39b072f3f": "存取記號的 {{app id}} 無效:{0}", 52 | "db8b02ad229f45cbb12e0d9845b09eb2": "{{OAuth 2.0 JWT}} 載送者策略需要 keying 回呼", 53 | "e173a3cecca19bcbf528408adc001750": "未獲授權的回應類型:{0}", 54 | "e82c91e82424949d4390135e5e8adf1c": "{{MAC}} 記號無效", 55 | "eb30f051fcf0e7338bf4d8489f583378": "未獲授權的 {{scope}}:{0}", 56 | "ec30fea412580b611d7a274ee1163e5c": "遺漏必要的參數:{{response_type}}", 57 | "ec9ddf242c3da3b5cf44def6398706ec": "{{oauth2orize.refreshToken}} 交換需要 {{issue}} 回呼", 58 | "ed5c8e0055b1cae433e4c393ae04d555": "無效項目:{0}", 59 | "f06abf2e08aba65a62f4486bc2418413": "{{oauth2orize.revoke}} 中介軟體需要 {{server}} 引數", 60 | "f24b75ecdc45edb84b0c9fec3b6f1e5b": "無法載入 {{OAuth 2.0}} 交易:{0}", 61 | "f483b2bebd08d285c7009c6812f5ba24": "存取記號過期", 62 | "f50708df489d7811db692c0b601483f8": "遺漏必要的參數:{{client_id}}", 63 | "fa925eb4771bd2897f14b1de78ca0ed2": "無效主題:{0}", 64 | "fcdd5cf7956698312e899ddb708abbaf": "遺漏 assertion 參數", 65 | "fef19f407c562658e0132f1625ce968b": "未獲授權的授權類型:{0}", 66 | "ff7883d90a5fe850e026885759165406": "資源擁有者認證無效" 67 | } 68 | 69 | -------------------------------------------------------------------------------- /lib/errors/authorizationerror.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2012,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | var util = require('util'); 7 | /** 8 | * Module dependencies. 9 | */ 10 | var OAuth2Error = require('./oauth2error'); 11 | 12 | /** 13 | * `AuthorizationError` error. 14 | * 15 | * @api public 16 | */ 17 | function AuthorizationError(message, code, uri, status) { 18 | if (!status) { 19 | switch (code) { 20 | case 'invalid_request': status = 400; break; 21 | case 'invalid_client': status = 401; break; 22 | case 'unauthorized_client': status = 403; break; 23 | case 'access_denied': status = 403; break; 24 | case 'unsupported_response_type': status = 400; break; 25 | case 'invalid_scope': status = 400; break; 26 | case 'temporarily_unavailable': status = 503; break; 27 | } 28 | } 29 | 30 | OAuth2Error.call(this, message, code, uri, status); 31 | Error.captureStackTrace(this, arguments.callee); 32 | this.name = 'AuthorizationError'; 33 | } 34 | 35 | /** 36 | * Inherit from `OAuth2Error`. 37 | */ 38 | util.inherits(AuthorizationError, OAuth2Error); 39 | 40 | /** 41 | * Expose `AuthorizationError`. 42 | */ 43 | module.exports = AuthorizationError; 44 | -------------------------------------------------------------------------------- /lib/errors/badrequesterror.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2012,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | var util = require('util'); 7 | 8 | /** 9 | * `BadRequestError` error. 10 | * 11 | * @api public 12 | */ 13 | function BadRequestError(message) { 14 | Error.call(this); 15 | Error.captureStackTrace(this, arguments.callee); 16 | this.name = 'BadRequestError'; 17 | this.message = message; 18 | this.status = 400; 19 | } 20 | 21 | /** 22 | * Inherit from `Error`. 23 | */ 24 | util.inherits(BadRequestError, Error); 25 | 26 | /** 27 | * Expose `BadRequestError`. 28 | */ 29 | module.exports = BadRequestError; 30 | -------------------------------------------------------------------------------- /lib/errors/forbiddenerror.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2013,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | var util = require('util'); 7 | /** 8 | * `ForbiddenError` error. 9 | * 10 | * @api public 11 | */ 12 | function ForbiddenError(message) { 13 | Error.call(this); 14 | Error.captureStackTrace(this, arguments.callee); 15 | this.name = 'ForbiddenError'; 16 | this.message = message; 17 | this.status = 403; 18 | } 19 | 20 | /** 21 | * Inherit from `Error`. 22 | */ 23 | util.inherits(ForbiddenError, Error); 24 | 25 | /** 26 | * Expose `ForbiddenError`. 27 | */ 28 | module.exports = ForbiddenError; 29 | -------------------------------------------------------------------------------- /lib/errors/oauth2error.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2015,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | /** 7 | * `OAuth2Error` error. 8 | * 9 | * @api public 10 | */ 11 | function OAuth2Error(message, code, uri, status) { 12 | Error.call(this); 13 | this.message = message; 14 | this.code = code || 'server_error'; 15 | this.uri = uri; 16 | this.status = status || 500; 17 | } 18 | 19 | /** 20 | * Inherit from `Error`. 21 | */ 22 | OAuth2Error.prototype.__proto__ = Error.prototype; 23 | 24 | /** 25 | * Expose `OAuth2Error`. 26 | */ 27 | module.exports = OAuth2Error; 28 | -------------------------------------------------------------------------------- /lib/errors/tokenerror.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2013,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | var util = require('util'); 7 | /** 8 | * Module dependencies. 9 | */ 10 | var OAuth2Error = require('./oauth2error'); 11 | 12 | /** 13 | * `TokenError` error. 14 | * 15 | * @api public 16 | */ 17 | function TokenError(message, code, uri, status) { 18 | if (!status) { 19 | switch (code) { 20 | case 'invalid_request': status = 400; break; 21 | case 'invalid_client': status = 401; break; 22 | case 'invalid_grant': status = 403; break; 23 | case 'unauthorized_client': status = 403; break; 24 | case 'unsupported_grant_type': status = 400; break; 25 | case 'invalid_scope': status = 400; break; 26 | case 'unsupported_token_type': status = 400; break; 27 | } 28 | } 29 | 30 | OAuth2Error.call(this, message, code, uri, status); 31 | Error.captureStackTrace(this, arguments.callee); 32 | this.name = 'TokenError'; 33 | } 34 | 35 | /** 36 | * Inherit from `OAuth2Error`. 37 | */ 38 | util.inherits(TokenError, OAuth2Error); 39 | 40 | /** 41 | * Expose `TokenError`. 42 | */ 43 | module.exports = TokenError; 44 | -------------------------------------------------------------------------------- /lib/exchange/authorizationCode.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2012,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | /** 8 | * Module dependencies. 9 | */ 10 | const SG = require('strong-globalize'); 11 | const g = SG(); 12 | const utils = require('../utils'), 13 | TokenError = require('../errors/tokenerror'); 14 | 15 | /** 16 | * Exchanges authorization codes for access tokens. 17 | * 18 | * This exchange middleware is used to by clients to obtain an access token by 19 | * presenting an authorization code. An authorization code must have previously 20 | * been issued, as handled by `code` grant middleware. 21 | * 22 | * Callbacks: 23 | * 24 | * This middleware requires an `issue` callback, for which the function 25 | * signature is as follows: 26 | * 27 | * function(client, code, redirectURI, done) { ... } 28 | * 29 | * `client` is the authenticated client instance attempting to obtain an access 30 | * token. `code` is the authorization code the client is in possession of. 31 | * `redirectURI` is the redirect URI specified by the client, being used as a 32 | * verifier which must match the value in the initial authorization request. 33 | * `done` is called to issue an access token: 34 | * 35 | * done(err, accessToken, refreshToken, params) 36 | * 37 | * `accessToken` is the access token that will be sent to the client. An 38 | * optional `refreshToken` will be sent to the client, if the server chooses to 39 | * implement support for this functionality. Any additional `params` will be 40 | * included in the response. If an error occurs, `done` should be invoked with 41 | * `err` set in idomatic Node.js fashion. 42 | * 43 | * Options: 44 | * 45 | * userProperty property of `req` which contains the authenticated client (default: 'user') 46 | * 47 | * Examples: 48 | * 49 | * server.exchange(oauth2orize.exchange.authorizationCode(function(client, code, redirectURI, done) { 50 | * AccessToken.create(client, code, redirectURI, function(err, accessToken) { 51 | * if (err) { return done(err); } 52 | * done(null, accessToken); 53 | * }); 54 | * })); 55 | * 56 | * References: 57 | * - [Authorization Code](http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-1.3.1) 58 | * - [Authorization Code Grant](http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-4.1) 59 | * 60 | * @param {Object} options 61 | * @param {Function} issue 62 | * @return {Function} 63 | * @api public 64 | */ 65 | module.exports = function(options, issue) { 66 | if (typeof options === 'function') { 67 | issue = options; 68 | options = undefined; 69 | } 70 | options = options || {}; 71 | 72 | if (!issue) { throw new TypeError(g.f('{{oauth2orize.authorizationCode}} exchange requires an issue callback')); } 73 | 74 | const userProperty = options.userProperty || 'user'; 75 | 76 | return function authorization_code(req, res, next) { 77 | if (!req.body) { 78 | return next(new Error(g.f( 79 | '{{OAuth2orize}} requires body parsing. Did you forget {{app.use(express.bodyParser())}}?' 80 | ))); 81 | } 82 | 83 | // The 'user' property of `req` holds the authenticated user. In the case 84 | // of the token endpoint, the property will contain the OAuth 2.0 client. 85 | const client = req[userProperty], 86 | code = req.body.code, 87 | redirectURI = req.body.redirect_uri; 88 | 89 | if (!code) { return next(new TokenError(g.f('Missing required parameter: {{code}}'), 'invalid_request')); } 90 | 91 | try { 92 | issue(client, code, redirectURI, function(err, accessToken, refreshToken, params) { 93 | if (err) { return next(err); } 94 | if (!accessToken) { return next(new TokenError(g.f('Invalid authorization code'), 'invalid_grant')); } 95 | if (refreshToken && typeof refreshToken == 'object') { 96 | params = refreshToken; 97 | refreshToken = null; 98 | } 99 | 100 | const tok = {}; 101 | tok.access_token = accessToken; 102 | if (refreshToken) { tok.refresh_token = refreshToken; } 103 | if (params) { utils.merge(tok, params); } 104 | tok.token_type = tok.token_type || 'Bearer'; 105 | 106 | const json = JSON.stringify(tok); 107 | res.setHeader('Content-Type', 'application/json'); 108 | res.setHeader('Cache-Control', 'no-store'); 109 | res.setHeader('Pragma', 'no-cache'); 110 | res.end(json); 111 | }); 112 | } catch (ex) { 113 | return next(ex); 114 | } 115 | }; 116 | }; 117 | -------------------------------------------------------------------------------- /lib/exchange/clientCredentials.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2012,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | /** 8 | * Module dependencies. 9 | */ 10 | const SG = require('strong-globalize'); 11 | const g = SG(); 12 | const utils = require('../utils'), 13 | TokenError = require('../errors/tokenerror'); 14 | 15 | /** 16 | * Exchanges client credentials for access tokens. 17 | * 18 | * This exchange middleware is used to by clients to obtain an access token by 19 | * presenting client credentials. 20 | * 21 | * Callbacks: 22 | * 23 | * This middleware requires an `issue` callback, for which the function 24 | * signature is as follows: 25 | * 26 | * function(client, scope, done) { ... } 27 | * 28 | * `client` is the authenticated client instance attempting to obtain an access 29 | * token. `scope` is the scope of access requested by the client. `done` is 30 | * called to issue an access token: 31 | * 32 | * done(err, accessToken, [refreshToken], [params]) 33 | * 34 | * `accessToken` is the access token that will be sent to the client. An 35 | * optional `refreshToken` will be sent to the client, if the server chooses to 36 | * implement support for this functionality (note that the spec says a refresh 37 | * token should not be included). Any additional `params` will be included in 38 | * the response. If an error occurs, `done` should be invoked with `err` set in 39 | * idomatic Node.js fashion. 40 | * 41 | * Options: 42 | * 43 | * userProperty property of `req` which contains the authenticated client (default: 'user') 44 | * scopeSeparator separator used to demarcate scope values (default: ' ') 45 | * 46 | * Examples: 47 | * 48 | * server.exchange(oauth2orize.exchange.clientCredentials(function(client, scope, done) { 49 | * AccessToken.create(client, scope, function(err, accessToken) { 50 | * if (err) { return done(err); } 51 | * done(null, accessToken); 52 | * }); 53 | * })); 54 | * 55 | * References: 56 | * - [Client Credentials](http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-1.3.4) 57 | * - [Client Credentials Grant](http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-4.4) 58 | * 59 | * @param {Object} options 60 | * @param {Function} issue 61 | * @return {Function} 62 | * @api public 63 | */ 64 | module.exports = function(options, issue) { 65 | if (typeof options === 'function') { 66 | issue = options; 67 | options = undefined; 68 | } 69 | options = options || {}; 70 | 71 | if (!issue) { throw new TypeError(g.f('{{oauth2orize.clientCredentials}} exchange requires an issue callback')); } 72 | 73 | const userProperty = options.userProperty || 'user'; 74 | 75 | // For maximum flexibility, multiple scope spearators can optionally be 76 | // allowed. This allows the server to accept clients that separate scope 77 | // with either space or comma (' ', ','). This violates the specification, 78 | // but achieves compatibility with existing client libraries that are already 79 | // deployed. 80 | let separators = options.scopeSeparator || ' '; 81 | if (!Array.isArray(separators)) { 82 | separators = [separators]; 83 | } 84 | 85 | return function client_credentials(req, res, next) { 86 | if (!req.body) { 87 | return next(new Error(g.f( 88 | '{{OAuth2orize}} requires body parsing. Did you forget {{app.use(express.bodyParser())}}?' 89 | ))); 90 | } 91 | 92 | // The 'user' property of `req` holds the authenticated user. In the case 93 | // of the token endpoint, the property will contain the OAuth 2.0 client. 94 | const client = req[userProperty]; 95 | let scope = req.body.scope; 96 | 97 | if (scope) { 98 | for (let i = 0, len = separators.length; i < len; i++) { 99 | const separated = scope.split(separators[i]); 100 | // only separate on the first matching separator. this allows for a sort 101 | // of separator "priority" (ie, favor spaces then fallback to commas) 102 | if (separated.length > 1) { 103 | scope = separated; 104 | break; 105 | } 106 | } 107 | if (!Array.isArray(scope)) { scope = [scope]; } 108 | } 109 | 110 | function issued(err, accessToken, refreshToken, params) { 111 | if (err) { return next(err); } 112 | if (!accessToken) { 113 | return next(new TokenError(g.f('Invalid client credentials'), 'invalid_grant')); 114 | } 115 | if (refreshToken && typeof refreshToken === 'object') { 116 | params = refreshToken; 117 | refreshToken = null; 118 | } 119 | 120 | const tok = {}; 121 | tok.access_token = accessToken; 122 | if (refreshToken) { tok.refresh_token = refreshToken; } 123 | if (params) { utils.merge(tok, params); } 124 | tok.token_type = tok.token_type || 'Bearer'; 125 | 126 | const json = JSON.stringify(tok); 127 | res.setHeader('Content-Type', 'application/json'); 128 | res.setHeader('Cache-Control', 'no-store'); 129 | res.setHeader('Pragma', 'no-cache'); 130 | res.end(json); 131 | } 132 | 133 | try { 134 | const arity = issue.length; 135 | if (arity === 4) { 136 | // Allow subject (username or email) to be specified 137 | const subject = req.body.sub || req.body.subject || req.body.username; 138 | issue(client, subject, scope, issued); 139 | } else if (arity === 3) { 140 | issue(client, scope, issued); 141 | } else { // arity == 2 142 | issue(client, issued); 143 | } 144 | } catch (ex) { 145 | return next(ex); 146 | } 147 | }; 148 | }; 149 | -------------------------------------------------------------------------------- /lib/exchange/jwt.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2014,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | /** 8 | * Module dependencies. 9 | */ 10 | const SG = require('strong-globalize'); 11 | const g = SG(); 12 | const AuthorizationError = require('../errors/authorizationerror'); 13 | 14 | /** 15 | * Merge object b with object a. 16 | * 17 | * var a = { foo: 'bar' } 18 | * , b = { bar: 'baz' }; 19 | * 20 | * utils.merge(a, b); 21 | * // => { foo: 'bar', bar: 'baz' } 22 | * 23 | * @param {Object} a 24 | * @param {Object} b 25 | * @return {Object} 26 | * @api private 27 | */ 28 | function merge(a, b) { 29 | if (a && b) { 30 | for (const key in b) { 31 | a[key] = b[key]; 32 | } 33 | } 34 | return a; 35 | } 36 | 37 | /** 38 | * JWT access tokens request. 39 | * 40 | * This exchange middleware is used to by clients to request an access token by 41 | * using a JSON Web Token (JWT) generated by the client and verified by a 42 | * Public Key stored on the server. 43 | * 44 | * Callbacks: 45 | * 46 | * This middleware requires an `issue` callback, for which the function 47 | * signature is as follows: 48 | * 49 | * function(client, data, signature, done) { ... } 50 | * 51 | * `client` is the authenticated client instance attempting to obtain an access 52 | * token. `data` is the JWT encoded header and claim set concatenated with a 53 | * period '.', `signature` is the signature portion of the JWT. `done` is 54 | * called to issue an access token: 55 | * 56 | * done(err, accessToken, params) 57 | * 58 | * `accessToken` is the access token that will be sent to the client. Any 59 | * additional `params` will be included in the response. If an error occurs, 60 | * `done` should be invoked with `err` set in idomatic Node.js fashion. 61 | * 62 | * Options: 63 | * 64 | * userProperty property of `req` which contains the authenticated client (default: 'user') 65 | * 66 | * Examples: 67 | * 68 | * server.exchange('urn:ietf:params:oauth:grant-type:jwt-bearer', oauth2orize.exchange.jwtBearer(function(client, data, signature, done) { 69 | * var crypto = require('crypto') 70 | * , pub = pubKey // TODO - Load your pubKey registered to the client from the file system or database 71 | * , verifier = crypto.createVerify("RSA-SHA256"); 72 | * 73 | * verifier.update(JSON.stringify(data)); 74 | * 75 | * if (verifier.verify(pub, signature, 'base64')) { 76 | * 77 | * // TODO - base64url decode data then verify client_id, scope and expiration are valid 78 | * 79 | * AccessToken.create(client, scope, function(err, accessToken) { 80 | * if (err) { return done(err); } 81 | * done(null, accessToken); 82 | * }); 83 | * } 84 | * })); 85 | * 86 | * References: 87 | * - [JSON Web Token (JWT) Bearer Token Profiles for OAuth 2.0](http://tools.ietf.org/html/draft-jones-oauth-jwt-bearer-01) 88 | * - [JSON Web Token (JWT)](http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-06) 89 | * - [Using OAuth 2.0 for Server to Server Applications](https://developers.google.com/accounts/docs/OAuth2ServiceAccount) 90 | * 91 | * @param {Object} options 92 | * @param {Function} issue 93 | * @api public 94 | */ 95 | module.exports = function jwtBearer(options, issue) { 96 | if (typeof options === 'function') { 97 | issue = options; 98 | options = null; 99 | } 100 | options = options || {}; 101 | 102 | if (!issue) { 103 | throw new Error(g.f('{{OAuth 2.0 jwtBearer}} exchange middleware requires an {{issue}} function.')); 104 | } 105 | 106 | const userProperty = options.userProperty || 'user'; 107 | 108 | return function jwt_bearer(req, res, next) { 109 | if (!req.body) { 110 | return next(new Error(g.f('Request body not parsed. Use {{bodyParser}} middleware.'))); 111 | } 112 | 113 | // The 'user' property of `req` holds the authenticated user. In the case 114 | // of the token endpoint, the property will contain the OAuth 2.0 client. 115 | let contents = []; 116 | const client = req[userProperty], 117 | jwtBearer = req.body['assertion'], 118 | separator = '.'; 119 | 120 | if (!jwtBearer) { 121 | return next(new AuthorizationError(g.f('missing assertion parameter'), 'invalid_request')); 122 | } 123 | 124 | contents = jwtBearer.split(separator); 125 | 126 | if (!Array.isArray(contents)) { 127 | contents = [contents]; 128 | } 129 | 130 | function issued(err, accessToken, params) { 131 | if (err) { 132 | return next(err); 133 | } 134 | if (!accessToken) { 135 | return next(new AuthorizationError(g.f('invalid {{JWT}}'), 'invalid_grant')); 136 | } 137 | 138 | const tok = {}; 139 | tok['access_token'] = accessToken; 140 | if (params) { 141 | merge(tok, params); 142 | } 143 | tok['token_type'] = tok['token_type'] || 'bearer'; 144 | 145 | const json = JSON.stringify(tok); 146 | res.setHeader('Content-Type', 'application/json'); 147 | res.setHeader('Cache-Control', 'no-store'); 148 | res.setHeader('Pragma', 'no-cache'); 149 | res.end(json); 150 | } 151 | 152 | const arity = issue.length; 153 | if (arity === 5) { 154 | // contents[0] = header, contents[1] = claimSet, contents[2] = signature 155 | issue(client, contents[0], contents[1], contents[2], issued); 156 | } else if (arity === 4) { 157 | // contents[0] = header, contents[1] = claimSet, contents[2] = signature 158 | const data = contents[0] + separator + contents[1]; 159 | issue(client, data, contents[2], issued); 160 | } else { // arity == 3 161 | issue(client, jwtBearer, issued); 162 | } 163 | }; 164 | }; 165 | -------------------------------------------------------------------------------- /lib/exchange/password.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2012,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | /** 8 | * Module dependencies. 9 | */ 10 | const SG = require('strong-globalize'); 11 | const g = SG(); 12 | const utils = require('../utils'), 13 | TokenError = require('../errors/tokenerror'); 14 | 15 | /** 16 | * Exchanges resource owner password credentials for access tokens. 17 | * 18 | * This exchange middleware is used to by clients to obtain an access token by 19 | * presenting the resource owner's password credentials. These credentials are 20 | * typically obtained directly from the user, by prompting them for input. 21 | * 22 | * Callbacks: 23 | * 24 | * This middleware requires an `issue` callback, for which the function 25 | * signature is as follows: 26 | * 27 | * function(client, username, password, scope, done) { ... } 28 | * 29 | * `client` is the authenticated client instance attempting to obtain an access 30 | * token. `username` and `password` and the resource owner's credentials. 31 | * `scope` is the scope of access requested by the client. `done` is called to 32 | * issue an access token: 33 | * 34 | * done(err, accessToken, refreshToken, params) 35 | * 36 | * `accessToken` is the access token that will be sent to the client. An 37 | * optional `refreshToken` will be sent to the client, if the server chooses to 38 | * implement support for this functionality. Any additional `params` will be 39 | * included in the response. If an error occurs, `done` should be invoked with 40 | * `err` set in idomatic Node.js fashion. 41 | * 42 | * Options: 43 | * 44 | * userProperty property of `req` which contains the authenticated client (default: 'user') 45 | * scopeSeparator separator used to demarcate scope values (default: ' ') 46 | * 47 | * Examples: 48 | * 49 | * server.exchange(oauth2orize.exchange.password(function(client, username, password, scope, done) { 50 | * AccessToken.create(client, username, password, scope, function(err, accessToken) { 51 | * if (err) { return done(err); } 52 | * done(null, accessToken); 53 | * }); 54 | * })); 55 | * 56 | * References: 57 | * - [Resource Owner Password Credentials](http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-1.3.3) 58 | * - [Resource Owner Password Credentials Grant](http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-4.3) 59 | * 60 | * @param {Object} options 61 | * @param {Function} issue 62 | * @return {Function} 63 | * @api public 64 | */ 65 | module.exports = function(options, issue) { 66 | if (typeof options === 'function') { 67 | issue = options; 68 | options = undefined; 69 | } 70 | options = options || {}; 71 | 72 | if (!issue) { throw new TypeError(g.f('{{oauth2orize.password}} exchange requires an {{issue}} callback')); } 73 | 74 | const userProperty = options.userProperty || 'user'; 75 | 76 | // For maximum flexibility, multiple scope spearators can optionally be 77 | // allowed. This allows the server to accept clients that separate scope 78 | // with either space or comma (' ', ','). This violates the specification, 79 | // but achieves compatibility with existing client libraries that are already 80 | // deployed. 81 | let separators = options.scopeSeparator || ' '; 82 | if (!Array.isArray(separators)) { 83 | separators = [separators]; 84 | } 85 | 86 | return function password(req, res, next) { 87 | if (!req.body) { 88 | return next(new Error(g.f( 89 | '{{OAuth2orize}} requires body parsing. Did you forget {{app.use(express.bodyParser())}}?' 90 | ))); 91 | } 92 | 93 | // The 'user' property of `req` holds the authenticated user. In the case 94 | // of the token endpoint, the property will contain the OAuth 2.0 client. 95 | const client = req[userProperty], 96 | username = req.body.username, 97 | passwd = req.body.password; 98 | let scope = req.body.scope; 99 | 100 | if (!username) { return next(new TokenError(g.f('Missing required parameter: {{username}}'), 'invalid_request')); } 101 | if (!passwd) { return next(new TokenError(g.f('Missing required parameter: {{password}}'), 'invalid_request')); } 102 | 103 | if (scope) { 104 | for (let i = 0, len = separators.length; i < len; i++) { 105 | const separated = scope.split(separators[i]); 106 | // only separate on the first matching separator. this allows for a sort 107 | // of separator "priority" (ie, favor spaces then fallback to commas) 108 | if (separated.length > 1) { 109 | scope = separated; 110 | break; 111 | } 112 | } 113 | if (!Array.isArray(scope)) { scope = [scope]; } 114 | } 115 | 116 | function issued(err, accessToken, refreshToken, params) { 117 | if (err) { return next(err); } 118 | if (!accessToken) { return next(new TokenError(g.f('Invalid resource owner credentials'), 'invalid_grant')); } 119 | if (refreshToken && typeof refreshToken == 'object') { 120 | params = refreshToken; 121 | refreshToken = null; 122 | } 123 | 124 | const tok = {}; 125 | tok.access_token = accessToken; 126 | if (refreshToken) { tok.refresh_token = refreshToken; } 127 | if (params) { utils.merge(tok, params); } 128 | tok.token_type = tok.token_type || 'Bearer'; 129 | 130 | const json = JSON.stringify(tok); 131 | res.setHeader('Content-Type', 'application/json'); 132 | res.setHeader('Cache-Control', 'no-store'); 133 | res.setHeader('Pragma', 'no-cache'); 134 | res.end(json); 135 | } 136 | 137 | try { 138 | const arity = issue.length; 139 | if (arity === 5) { 140 | issue(client, username, passwd, scope, issued); 141 | } else { // arity == 4 142 | issue(client, username, passwd, issued); 143 | } 144 | } catch (ex) { 145 | return next(ex); 146 | } 147 | }; 148 | }; 149 | -------------------------------------------------------------------------------- /lib/exchange/refreshToken.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2012,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | /** 8 | * Module dependencies. 9 | */ 10 | const SG = require('strong-globalize'); 11 | const g = SG(); 12 | const utils = require('../utils'), 13 | TokenError = require('../errors/tokenerror'); 14 | 15 | /** 16 | * Refresh previously issued access tokens. 17 | * 18 | * This exchange middleware is used to by clients to refresh an access token by 19 | * using a refresh token issued by the server. 20 | * 21 | * Callbacks: 22 | * 23 | * This middleware requires an `issue` callback, for which the function 24 | * signature is as follows: 25 | * 26 | * function(client, refreshToken, scope, done) { ... } 27 | * 28 | * `client` is the authenticated client instance attempting to obtain an access 29 | * token. `refreshToken` is the refresh token issued by the server. `scope` is 30 | * the scope of access requested by the client, which must not include any scope 31 | * not originally granted. `done` is called to issue an access token: 32 | * 33 | * done(err, accessToken, refreshToken, params) 34 | * 35 | * `accessToken` is the access token that will be sent to the client. An 36 | * optional `refreshToken` will be sent to the client, if the server chooses to 37 | * implement support for this functionality. Any additional `params` will be 38 | * included in the response. If an error occurs, `done` should be invoked with 39 | * `err` set in idomatic Node.js fashion. 40 | * 41 | * Options: 42 | * 43 | * userProperty property of `req` which contains the authenticated client (default: 'user') 44 | * scopeSeparator separator used to demarcate scope values (default: ' ') 45 | * 46 | * Examples: 47 | * 48 | * server.exchange(oauth2orize.exchange.refreshToken(function(client, refreshToken, scope, done) { 49 | * AccessToken.create(client, refreshToken, scope, function(err, accessToken) { 50 | * if (err) { return done(err); } 51 | * done(null, accessToken); 52 | * }); 53 | * })); 54 | * 55 | * References: 56 | * - [Refreshing an Access Token](http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-6) 57 | * 58 | * @param {Object} options 59 | * @param {Function} issue 60 | * @api public 61 | */ 62 | module.exports = function(options, issue) { 63 | if (typeof options === 'function') { 64 | issue = options; 65 | options = undefined; 66 | } 67 | options = options || {}; 68 | 69 | if (!issue) { throw new TypeError(g.f('{{oauth2orize.refreshToken}} exchange requires an {{issue}} callback')); } 70 | 71 | const userProperty = options.userProperty || 'user'; 72 | 73 | // For maximum flexibility, multiple scope spearators can optionally be 74 | // allowed. This allows the server to accept clients that separate scope 75 | // with either space or comma (' ', ','). This violates the specification, 76 | // but achieves compatibility with existing client libraries that are already 77 | // deployed. 78 | let separators = options.scopeSeparator || ' '; 79 | if (!Array.isArray(separators)) { 80 | separators = [separators]; 81 | } 82 | 83 | return function refresh_token(req, res, next) { 84 | if (!req.body) { 85 | return next(new Error(g.f( 86 | '{{OAuth2orize}} requires body parsing. Did you forget {{app.use(express.bodyParser())}}?' 87 | ))); 88 | } 89 | 90 | // The 'user' property of `req` holds the authenticated user. In the case 91 | // of the token endpoint, the property will contain the OAuth 2.0 client. 92 | const client = req[userProperty], 93 | refreshToken = req.body.refresh_token; 94 | let scope = req.body.scope; 95 | 96 | if (!refreshToken) { 97 | return next(new TokenError(g.f( 98 | 'Missing required parameter: {{refresh_token}}' 99 | ), 'invalid_request')); 100 | } 101 | 102 | if (scope) { 103 | for (let i = 0, len = separators.length; i < len; i++) { 104 | const separated = scope.split(separators[i]); 105 | // only separate on the first matching separator. this allows for a sort 106 | // of separator "priority" (ie, favor spaces then fallback to commas) 107 | if (separated.length > 1) { 108 | scope = separated; 109 | break; 110 | } 111 | } 112 | if (!Array.isArray(scope)) { scope = [scope]; } 113 | } 114 | 115 | function issued(err, accessToken, refreshToken, params) { 116 | if (err) { return next(err); } 117 | if (!accessToken) { return next(new TokenError(g.f('Invalid refresh token'), 'invalid_grant')); } 118 | if (refreshToken && typeof refreshToken === 'object') { 119 | params = refreshToken; 120 | refreshToken = null; 121 | } 122 | 123 | const tok = {}; 124 | tok.access_token = accessToken; 125 | if (refreshToken) { tok.refresh_token = refreshToken; } 126 | if (params) { utils.merge(tok, params); } 127 | tok.token_type = tok.token_type || 'Bearer'; 128 | 129 | const json = JSON.stringify(tok); 130 | res.setHeader('Content-Type', 'application/json'); 131 | res.setHeader('Cache-Control', 'no-store'); 132 | res.setHeader('Pragma', 'no-cache'); 133 | res.end(json); 134 | } 135 | 136 | try { 137 | const arity = issue.length; 138 | if (arity === 4) { 139 | issue(client, refreshToken, scope, issued); 140 | } else { // arity == 3 141 | issue(client, refreshToken, issued); 142 | } 143 | } catch (ex) { 144 | return next(ex); 145 | } 146 | }; 147 | }; 148 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2012,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | /** 8 | * Module dependencies. 9 | */ 10 | const path = require('path'); 11 | const SG = require('strong-globalize'); 12 | SG.SetRootDir(path.join(__dirname, '..')); 13 | const g = SG(); 14 | const loopbackOAuth2 = require('./oauth2-loopback'); 15 | exports = module.exports = loopbackOAuth2; 16 | 17 | exports.oAuth2Provider = loopbackOAuth2; // Keep backward-compatibility 18 | exports.oauth2orize = require('./oauth2orize'); 19 | 20 | /** 21 | * A factory function for middleware handler that obtains the `authentication` 22 | * handler configured by the OAuth2 component. 23 | */ 24 | exports.authenticate = function(options) { 25 | let router; 26 | return function oauth2AuthenticateHandler(req, res, next) { 27 | if (!router) { 28 | const app = req.app; 29 | const authenticate = app._oauth2Handlers && app._oauth2Handlers.authenticate; 30 | 31 | if (!authenticate) { 32 | return next(new Error(g.f( 33 | 'The {{OAuth2}} component was not configured for this application.' 34 | ))); 35 | } 36 | 37 | const handlers = authenticate(options); 38 | router = app.loopback.Router(); 39 | for (let i = 0, n = handlers.length; i < n; i++) { 40 | router.use(handlers[i]); 41 | } 42 | } 43 | 44 | return router(req, res, next); 45 | }; 46 | }; 47 | -------------------------------------------------------------------------------- /lib/mac-token.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2015,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | const crypto = require('crypto'); 8 | const utils = require('./utils'); 9 | const helpers = require('./oauth2-helper'); 10 | const jwt = require('jws'); 11 | const debug = require('debug')('loopback:oauth2'); 12 | 13 | const algorithms = { 14 | 'hmac-sha-1': 'sha1', 15 | 'hmac-sha-256': 'sha256', 16 | }; 17 | 18 | module.exports = MACTokenGenerator; 19 | 20 | function MACTokenGenerator(algorithm) { 21 | this.algorithm = algorithms[algorithm] || algorithm || 'sha1'; 22 | } 23 | 24 | MACTokenGenerator.prototype.encode = function(key, text, encoding) { 25 | return crypto.createHmac(this.algorithm, key) 26 | .update(text).digest(encoding || 'base64'); 27 | }; 28 | 29 | MACTokenGenerator.prototype.generateToken = function(options) { 30 | const algorithm = this.algorithm === 'sha1' ? 'hmac-sha-1' : 'hmac-sha-256'; 31 | const key = utils.uid(32); 32 | 33 | const payload = { 34 | iss: options.client.id, // issuer - client id 35 | sub: options.user && options.user.id, // subject 36 | aud: '/oauth/token', // audience 37 | exp: Date.now() + options.ttl * 1000, // expiration time 38 | iat: Date.now(), // issued at time 39 | scope: options.scope, // a list of oAuth 2.0 scopes 40 | mac_algorithm: algorithm, 41 | mac_key: key, 42 | }; 43 | 44 | const secret = options.client.clientSecret || options.client.restApiKey; 45 | const jwtAlgorithm = options.jwtAlgorithm || 'HS256'; 46 | 47 | // Sign the access token 48 | const token = helpers.generateJWT(payload, secret, jwtAlgorithm); 49 | const kid = crypto.createHash('sha1').update(token).digest('base64'); 50 | 51 | return { 52 | id: token, 53 | token_type: 'mac', 54 | kid: kid, 55 | mac_algorithm: algorithm, 56 | mac_key: key, 57 | }; 58 | }; 59 | 60 | MACTokenGenerator.prototype.validate = function(req) { 61 | let authorizationHeader = req.get('authorization'); 62 | if (!authorizationHeader) { 63 | return null; 64 | } 65 | // Parser the header 66 | /* 67 | Authorization: MAC access_token="h480djs93hd8", 68 | ts="1336363200", 69 | kid="dj83hs9s", 70 | mac="bhCQXTVyfj5cmA9uKkPFx1zeOXM=" 71 | */ 72 | 73 | const params = {}; 74 | let i; 75 | let n; 76 | if (authorizationHeader.indexOf('MAC ') === 0) { 77 | authorizationHeader = authorizationHeader.substring(4); 78 | const parts = authorizationHeader.split(/[,\s]+/).filter(Boolean); 79 | for (i = 0, n = parts.length; i < n; i++) { 80 | const part = parts[i]; 81 | const index = part.indexOf('='); 82 | const kv = []; 83 | kv[0] = part.substring(0, index); 84 | kv[1] = part.substring(index + 1); 85 | let val = kv[1]; 86 | if (val[0] === '"') { 87 | val = val.substring(1, val.length - 1); 88 | } 89 | params[kv[0]] = val; 90 | } 91 | } else { 92 | return null; 93 | } 94 | 95 | debug('MAC authorization: %s', authorizationHeader); 96 | 97 | const h = params.h || 'host'; 98 | // var seqNr = params['seq-nr']; 99 | // var cb = params.cb; 100 | // var kid = params.kid; 101 | const ts = Number(params.ts) || 0; 102 | if ((Date.now() - ts) / 1000 > 300) { 103 | debug('Timestamp expired: %d', ts); 104 | return null; 105 | } 106 | const method = req.method.toUpperCase(); 107 | const reqUri = req.originalUrl; 108 | const mac = params.mac; 109 | 110 | // Add header values 111 | const headers = []; 112 | const headerNames = h.split(/[,\s]+/).filter(Boolean); 113 | for (i = 0, n = headerNames.length; i < n; i++) { 114 | const header = req.get(headerNames[i]) || ''; 115 | headers.push(header); 116 | } 117 | 118 | const accessToken = jwt.decode(params.access_token, {json: true}); 119 | debug('Decoded access token: %j', accessToken); 120 | 121 | const text = [ 122 | method + ' ' + reqUri + ' HTTP/' + req.httpVersion, ts, 123 | ].concat(headers).join('\n'); 124 | 125 | const signature = this.encode(accessToken.payload.mac_key, text); 126 | 127 | debug('Input string: %s, key: %s, mac: %s', 128 | text, accessToken.payload.mac_key, signature); 129 | 130 | if (mac !== signature) { 131 | debug('MAC signature does not match'); 132 | return null; 133 | } 134 | 135 | return params.access_token; 136 | }; 137 | -------------------------------------------------------------------------------- /lib/middleware/decision.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2012,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | /** 8 | * Module dependencies. 9 | */ 10 | const SG = require('strong-globalize'); 11 | const g = SG(); 12 | const AuthorizationError = require('../errors/authorizationerror'), 13 | ForbiddenError = require('../errors/forbiddenerror'); 14 | 15 | /** 16 | * Handle authorization decisions from resource owners. 17 | * 18 | * Obtaining authorization via OAuth 2.0 consists of a sequence of discrete 19 | * steps. First, the client requests authorization from the user (in this case 20 | * using an authorization server as an intermediary). The authorization server 21 | * conducts an approval dialog with the user to obtain permission. After access 22 | * has been allowed, a grant is issued to the client which can be exchanged for 23 | * an access token. 24 | * 25 | * This middleware is used to process a user's decision about whether to allow 26 | * or deny access. The client that initiated the authorization transaction will 27 | * be sent a response, including a grant if access was allowed. 28 | * 29 | * The exact form of the grant will depend on the type requested by the client. 30 | * The `server`'s response handling functions are used to issue the grant and 31 | * send the response. An application can implement support for these types as 32 | * necessary, including taking advantage of bundled grant middleware. 33 | * 34 | * Callbacks: 35 | * 36 | * An optional `parse` callback can be passed as an argument, for which the 37 | * function signature is as follows: 38 | * 39 | * function(req, done) { ... } 40 | * 41 | * `req` is the request, which can be parsed for any additional parameters found 42 | * in query as required by the service provider. `done` is a callback which 43 | * must be invoked with the following signature: 44 | * 45 | * done(err, params); 46 | * 47 | * `params` are the additional parameters parsed from the request. These will 48 | * be set on the transaction at `req.oauth2.res`. If an error occurs, `done` 49 | * should be invoked with `err` set in idomatic Node.js fashion. 50 | * 51 | * Options: 52 | * 53 | * cancelField name of field that is set if user denied access (default: 'cancel') 54 | * userProperty property of `req` which contains the authenticated user (default: 'user') 55 | * sessionKey key under which transactions are stored in the session (default: 'authorize') 56 | * 57 | * Examples: 58 | * 59 | * app.post('/dialog/authorize/decision', 60 | * login.ensureLoggedIn(), 61 | * server.decision()); 62 | * 63 | * app.post('/dialog/authorize/decision', 64 | * login.ensureLoggedIn(), 65 | * server.decision(function(req, done) { 66 | * return done(null, { scope: req.scope }) 67 | * })); 68 | * 69 | * @param {Server} server 70 | * @param {Object} options 71 | * @param {Function} parse 72 | * @return {Function} 73 | * @api protected 74 | */ 75 | module.exports = function(server, options, parse) { 76 | if (typeof options == 'function') { 77 | parse = options; 78 | options = undefined; 79 | } 80 | options = options || {}; 81 | parse = parse || function(req, done) { return done(); }; 82 | 83 | if (!server) { throw new TypeError(g.f('{{oauth2orize.decision}} middleware requires a {{server}} argument')); } 84 | 85 | const cancelField = options.cancelField || 'cancel', 86 | userProperty = options.userProperty || 'user', 87 | key = options.sessionKey || 'authorize'; 88 | 89 | return function decision(req, res, next) { 90 | if (!req.session) { 91 | return next(new Error(g.f( 92 | '{{OAuth2orize}} requires {{session}} support. Did you forget {{app.use(express.session(...))}}?' 93 | ))); 94 | } 95 | if (!req.body) { 96 | return next(new Error(g.f( 97 | '{{OAuth2orize}} requires body parsing. Did you forget {{app.use(express.bodyParser())}}?' 98 | ))); 99 | } 100 | if (!req.oauth2) { 101 | return next(new Error(g.f( 102 | '{{OAuth2orize}} requires transaction support. Did you forget {{oauth2orize.transactionLoader(...)}}?' 103 | ))); 104 | } 105 | if (!req.session[key]) { 106 | return next(new ForbiddenError(g.f('Unable to load {{OAuth 2.0}} transactions from session'))); 107 | } 108 | 109 | parse(req, function(err, ares) { 110 | if (err) { return next(err); } 111 | 112 | const tid = req.oauth2.transactionID; 113 | req.oauth2.user = req[userProperty]; 114 | req.oauth2.res = ares || {}; 115 | 116 | if (req.oauth2.res.allow === undefined) { 117 | if (!req.body[cancelField]) { 118 | req.oauth2.res.allow = true; 119 | } else { req.oauth2.res.allow = false; } 120 | } 121 | 122 | // proxy end() to delete the transaction 123 | const end = res.end; 124 | res.end = function(chunk, encoding) { 125 | delete req.session[key][tid]; 126 | res.end = end; 127 | res.end(chunk, encoding); 128 | }; 129 | 130 | server._respond(req.oauth2, res, function(err) { 131 | if (err) { return next(err); } 132 | return next(new AuthorizationError(g.f( 133 | 'Unsupported response type: %s', req.oauth2.req.type 134 | ), 'unsupported_response_type')); 135 | }); 136 | }); 137 | }; 138 | }; 139 | -------------------------------------------------------------------------------- /lib/middleware/errorHandler.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2012,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | /** 8 | * Module dependencies. 9 | */ 10 | const url = require('url'), 11 | qs = require('querystring'), 12 | UnorderedList = require('../unorderedlist'); 13 | 14 | /** 15 | * Handles errors encountered in OAuth 2.0 endpoints. 16 | * 17 | * This is error handling middleware intended for use in endpoints involved in 18 | * the OAuth 2.0 protocol. If an error occurs while processing a request, this 19 | * middleware formats a response in accordance with the OAuth 2.0 specification. 20 | * 21 | * This middleware has two modes of operation: direct and indirect. Direct mode 22 | * (the default) is intended to be used with the token endpoint, in which the 23 | * response can be sent directly to the client. Indirect mode is intended to be 24 | * used with user authorization endpoints, in which the response must be issued 25 | * to the client indirectly via a redirect through the user's browser. 26 | * 27 | * Options: 28 | * - `mode` mode of operation, defaults to `direct` 29 | * 30 | * Examples: 31 | * 32 | * app.post('/token', 33 | * passport.authenticate(['basic', 'oauth2-client-password'], { session: false }), 34 | * server.token(), 35 | * server.errorHandler()); 36 | * 37 | * app.get('/dialog/authorize', 38 | * login.ensureLoggedIn(), 39 | * server.authorization( ... ) 40 | * server.errorHandler({ mode: 'indirect' })); 41 | * 42 | * References: 43 | * - [Error Response](http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-5.2) 44 | * - [Authorization Response](http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-4.1.2) 45 | * - [Authorization Response](http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-4.2.2) 46 | * 47 | * @param {Object} options 48 | * @return {Function} 49 | * @api public 50 | */ 51 | module.exports = function(options) { 52 | options = options || {}; 53 | 54 | const mode = options.mode || 'direct', 55 | fragment = options.fragment || ['token']; 56 | 57 | function sendError(res, err) { 58 | if (err.status) { 59 | res.statusCode = err.status; 60 | } 61 | if (!res.statusCode || res.statusCode < 400) { 62 | res.statusCode = 500; 63 | } 64 | 65 | if (res.statusCode === 401) { 66 | res.setHeader('WWW-Authenticate', 67 | 'Basic realm="oAuth 2.0 client authentication"'); 68 | } 69 | 70 | const e = {}; 71 | e.error = err.code || 'server_error'; 72 | if (err.message) { 73 | e.error_description = err.message; 74 | } 75 | if (err.uri) { 76 | e.error_uri = err.uri; 77 | } 78 | 79 | res.setHeader('Content-Type', 'application/json'); 80 | return res.end(JSON.stringify(e)); 81 | } 82 | 83 | return function errorHandler(err, req, res, next) { 84 | if (mode === 'direct') { 85 | return sendError(res, err); 86 | } else if (mode === 'indirect') { 87 | // If the redirectURI for this OAuth 2.0 transaction is invalid, the user 88 | // agent will not be redirected and the client will not be informed. `next` 89 | // immediately into the application's error handler, so a message can be 90 | // displayed to the user. 91 | if (!req.oauth2 || !req.oauth2.redirectURI) { 92 | return sendError(res, err); 93 | } 94 | 95 | let enc = 'query'; 96 | if (req.oauth2.req) { 97 | const type = new UnorderedList(req.oauth2.req.type); 98 | // In accordance with [OAuth 2.0 Multiple Response Type Encoding 99 | // Practices - draft 08](http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html), 100 | // if the response type contains any value that requires fragment 101 | // encoding, the response will be fragment encoded. 102 | if (type.containsAny(fragment)) { enc = 'fragment'; } 103 | } 104 | 105 | const redirectURI = req.oauth2.redirectURI, 106 | uri = url.parse(redirectURI, true); 107 | 108 | if (enc === 'fragment') { 109 | const hash = {}; 110 | hash.error = err.code || 'server_error'; 111 | if (err.message) { hash.error_description = err.message; } 112 | if (err.uri) { hash.error_uri = err.uri; } 113 | if (req.oauth2.req && req.oauth2.req.state) { hash.state = req.oauth2.req.state; } 114 | uri.hash = qs.stringify(hash); 115 | } else { 116 | delete uri.search; 117 | uri.query.error = err.code || 'server_error'; 118 | if (err.message) { uri.query.error_description = err.message; } 119 | if (err.uri) { uri.query.error_uri = err.uri; } 120 | if (req.oauth2.req && req.oauth2.req.state) { uri.query.state = req.oauth2.req.state; } 121 | } 122 | 123 | const location = url.format(uri); 124 | res.redirect(location); 125 | } else { 126 | return next(err); 127 | } 128 | }; 129 | }; 130 | -------------------------------------------------------------------------------- /lib/middleware/revoke.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2015,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | /** 8 | * Module dependencies. 9 | */ 10 | const SG = require('strong-globalize'); 11 | const g = SG(); 12 | const TokenError = require('../errors/tokenerror'); 13 | 14 | /** 15 | * https://tools.ietf.org/html/rfc7009 16 | * 17 | * @param {Server} server 18 | * @param {Object} options 19 | * @return {Function} 20 | * @api protected 21 | */ 22 | module.exports = function revoke(server, options, revokeToken) { 23 | if (typeof options === 'function' && revokeToken === undefined) { 24 | revokeToken = options; 25 | options = {}; 26 | } 27 | options = options || {}; 28 | 29 | if (!server) { 30 | throw new TypeError(g.f( 31 | '{{oauth2orize.revoke}} middleware requires a {{server}} argument' 32 | )); 33 | } 34 | 35 | if (typeof revokeToken !== 'function') { 36 | throw new TypeError(g.f( 37 | '{{oauth2orize.revoke}} middleware requires a {{revokeToken}} function' 38 | )); 39 | } 40 | 41 | const userProperty = options.userProperty || 'user'; 42 | 43 | return function revoke(req, res, next) { 44 | // The 'user' property of `req` holds the authenticated user. In the case 45 | // of the token endpoint, the property will contain the OAuth 2.0 client. 46 | const client = req[userProperty]; 47 | 48 | const token = (req.body && req.body.token) || req.query.token; 49 | if (!token) { 50 | return next(new TokenError(g.f( 51 | 'Missing required parameter: {{token}}' 52 | ), 'invalid_request')); 53 | } 54 | const type = (req.body && req.body.token_type_hint) || 55 | req.query.token_type_hint || 'access_token'; 56 | 57 | if (type !== 'refresh_token' && type !== 'access_token') { 58 | return next(new TokenError(g.f( 59 | 'Unsupported token type: %s', type 60 | ), 'unsupported_token_type')); 61 | } 62 | 63 | revokeToken(client, token, type, function(err) { 64 | if (err) { 65 | return next(err); 66 | } else { 67 | res.status(200).end(); 68 | } 69 | }); 70 | }; 71 | }; 72 | -------------------------------------------------------------------------------- /lib/middleware/token.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2012,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | /** 8 | * Module dependencies. 9 | */ 10 | const SG = require('strong-globalize'); 11 | const g = SG(); 12 | const TokenError = require('../errors/tokenerror'); 13 | 14 | /** 15 | * Exchanges authorization grants for access tokens. 16 | * 17 | * Obtaining authorization via OAuth 2.0 consists of a sequence of discrete 18 | * steps. First, the client requests authorization from the user (in this case 19 | * using an authorization server as an intermediary). The authorization server 20 | * conducts an approval dialog with the user to obtain permission. After access 21 | * has been allowed, a grant is issued to the client which can be exchanged for 22 | * an access token. 23 | * 24 | * This middleware is used to exchange a previously issued authorization grant 25 | * for an access token (a string denoting a specific scope, lifetime, and other 26 | * access attributes). 27 | * 28 | * The types of the grants that can be exchanged will depend on the types 29 | * supported by the server. An application can implement support for these 30 | * types as necessary, including taking advantage of bundled grant and exchange 31 | * middleware. 32 | * 33 | * Note that clients issued credentials must authenticate when when making 34 | * requests to the token endpoint. This is essential for enforcing the binding 35 | * of authorization codes and refresh tokens to the client they were issued to. 36 | * Some client deployments may be incapable of secure client authentication. 37 | * Applications are responsible for determining what level of exposure is 38 | * acceptable, and handling such clients and displaying notices as appropriate. 39 | * 40 | * Examples: 41 | * 42 | * app.post('/token', 43 | * passport.authenticate(['basic', 'oauth2-client-password'], { session: false }), 44 | * server.token(), 45 | * server.errorHandler()); 46 | * 47 | * References: 48 | * - [Token Endpoint](http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-3.2) 49 | * 50 | * @param {Server} server 51 | * @param {Object} options 52 | * @return {Function} 53 | * @api protected 54 | */ 55 | module.exports = function token(server, options) { 56 | options = options || {}; 57 | 58 | if (!server) { throw new TypeError(g.f('{{oauth2orize.token}} middleware requires a {{server}} argument')); } 59 | 60 | return function token(req, res, next) { 61 | const type = req.body.grant_type; 62 | 63 | server._exchange(type, req, res, function(err) { 64 | if (err) { return next(err); } 65 | return next(new TokenError(g.f('Unsupported grant type: %s', type), 'unsupported_grant_type')); 66 | }); 67 | }; 68 | }; 69 | -------------------------------------------------------------------------------- /lib/middleware/transactionLoader.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2012,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | /** 8 | * Module dependencies. 9 | */ 10 | const SG = require('strong-globalize'); 11 | const g = SG(); 12 | const AuthorizationError = require('../errors/authorizationerror'), 13 | BadRequestError = require('../errors/badrequesterror'), 14 | ForbiddenError = require('../errors/forbiddenerror'); 15 | 16 | /** 17 | * Loads an OAuth 2.0 authorization transaction from the session. 18 | * 19 | * This middleware is used to load a pending OAuth 2.0 transaction that is 20 | * serialized into the session. In most circumstances, this is transparently 21 | * done prior to processing a user's decision with `decision` middleware, and an 22 | * implementation shouldn't need to mount this middleware explicitly. 23 | * 24 | * Options: 25 | * 26 | * transactionField name of field that contains the transaction ID (default: 'transaction_id') 27 | * sessionKey key under which transactions are stored in the session (default: 'authorize') 28 | * 29 | * @param {Server} server 30 | * @param {Object} options 31 | * @return {Function} 32 | * @api protected 33 | */ 34 | module.exports = function(server, options) { 35 | options = options || {}; 36 | 37 | if (!server) { 38 | throw new TypeError(g.f('{{oauth2orize.transactionLoader}} middleware requires a {{server}} argument')); 39 | } 40 | 41 | const field = options.transactionField || 'transaction_id', 42 | key = options.sessionKey || 'authorize'; 43 | 44 | return function transactionLoader(req, res, next) { 45 | if (!req.session) { 46 | return next(new Error(g.f( 47 | '{{OAuth2orize}} requires {{session}} support. Did you forget {{app.use(express.session(...))}}?' 48 | ))); 49 | } 50 | if (!req.session[key]) { 51 | return next(new ForbiddenError(g.f('Unable to load {{OAuth 2.0}} transactions from session'))); 52 | } 53 | 54 | const query = req.query || {}, 55 | body = req.body || {}, 56 | tid = query[field] || body[field]; 57 | 58 | if (!tid) { return next(new BadRequestError(g.f('Missing required parameter: %s', field))); } 59 | const txn = req.session[key][tid]; 60 | if (!txn) { return next(new ForbiddenError(g.f('Unable to load {{OAuth 2.0}} transaction: %s', tid))); } 61 | 62 | server.deserializeClient(txn.client, function(err, client) { 63 | if (err) { return next(err); } 64 | if (!client) { 65 | // At the time the request was initiated, the client was validated. 66 | // Since then, however, it has been invalidated. The transaction will 67 | // be invalidated and no response will be sent to the client. 68 | delete req.session[key][tid]; 69 | return next(new AuthorizationError(g.f('Unauthorized client'), 'unauthorized_client')); 70 | } 71 | 72 | req.oauth2 = {}; 73 | req.oauth2.transactionID = tid; 74 | req.oauth2.client = client; 75 | req.oauth2.redirectURI = txn.redirectURI; 76 | req.oauth2.req = txn.req; 77 | req.oauth2.info = txn.info; 78 | next(); 79 | }); 80 | }; 81 | }; 82 | -------------------------------------------------------------------------------- /lib/models/oauth2-models.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2014,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | const tokenDef = require('../../common/models/oauth-token.json'); 8 | const authorizationCodeDef = 9 | require('../../common/models/oauth-authorization-code.json'); 10 | const clientApplicationDef = 11 | require('../../common/models/oauth-client-application.json'); 12 | const permissionDef = 13 | require('../../common/models/oauth-permission.json'); 14 | const scopeDef = 15 | require('../../common/models/oauth-scope.json'); 16 | 17 | const scopeMappingDef = 18 | require('../../common/models/oauth-scope-mapping.json'); 19 | 20 | // Remove proerties that will confuse LB 21 | function getSettings(def) { 22 | const settings = {}; 23 | for (const s in def) { 24 | if (s === 'name' || s === 'properties') { 25 | continue; 26 | } else { 27 | settings[s] = def[s]; 28 | } 29 | } 30 | return settings; 31 | } 32 | 33 | module.exports = function(dataSource) { 34 | // "OAuth token" 35 | const OAuthToken = dataSource.createModel( 36 | tokenDef.name, tokenDef.properties, getSettings(tokenDef) 37 | ); 38 | 39 | // "OAuth authorization code" 40 | const OAuthAuthorizationCode = dataSource.createModel( 41 | authorizationCodeDef.name, 42 | authorizationCodeDef.properties, 43 | getSettings(authorizationCodeDef) 44 | ); 45 | 46 | // "OAuth client registration record" 47 | const OAuthClientApplication = dataSource.createModel( 48 | clientApplicationDef.name, 49 | clientApplicationDef.properties, 50 | getSettings(clientApplicationDef) 51 | ); 52 | 53 | // "OAuth permission" 54 | const OAuthPermission = dataSource.createModel( 55 | permissionDef.name, 56 | permissionDef.properties, 57 | getSettings(permissionDef) 58 | ); 59 | 60 | // "OAuth scope" 61 | const OAuthScope = dataSource.createModel( 62 | scopeDef.name, 63 | scopeDef.properties, 64 | getSettings(scopeDef) 65 | ); 66 | 67 | // "OAuth scope mapping" 68 | const OAuthScopeMapping = dataSource.createModel( 69 | scopeMappingDef.name, 70 | scopeMappingDef.properties, 71 | getSettings(scopeMappingDef) 72 | ); 73 | 74 | return { 75 | OAuthToken: OAuthToken, 76 | OAuthAuthorizationCode: OAuthAuthorizationCode, 77 | OAuthClientApplication: OAuthClientApplication, 78 | OAuthPermission: OAuthPermission, 79 | OAuthScope: OAuthScope, 80 | OAuthScopeMapping: OAuthScopeMapping, 81 | }; 82 | }; 83 | -------------------------------------------------------------------------------- /lib/oauth2orize.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2014,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | /** 8 | * Module dependencies. 9 | */ 10 | const fs = require('fs'), 11 | path = require('path'), 12 | Server = require('./server'); 13 | 14 | /** 15 | * Create an OAuth 2.0 server. 16 | * 17 | * @return {Server} 18 | * @api public 19 | */ 20 | function createServer() { 21 | const server = new Server(); 22 | return server; 23 | } 24 | 25 | exports = module.exports = createServer; 26 | 27 | /** 28 | * Export `.createServer()`. 29 | */ 30 | exports.createServer = createServer; 31 | 32 | /** 33 | * Export middleware. 34 | */ 35 | exports.errorHandler = require('./middleware/errorHandler'); 36 | 37 | function load(type) { 38 | function createLoader(type, name) { 39 | return function() { 40 | return require('./' + type + '/' + name); 41 | }; 42 | } 43 | fs.readdirSync(__dirname + '/' + type).forEach(function(filename) { 44 | if (/\.js$/.test(filename)) { 45 | const name = path.basename(filename, '.js'); 46 | exports[type].__defineGetter__(name, createLoader(type, name)); 47 | } 48 | }); 49 | } 50 | 51 | /** 52 | * Auto-load bundled grants. 53 | */ 54 | exports.grant = {}; 55 | load('grant'); 56 | 57 | // alias grants 58 | exports.grant.authorizationCode = exports.grant.code; 59 | exports.grant.implicit = exports.grant.token; 60 | 61 | /** 62 | * Auto-load bundled exchanges. 63 | */ 64 | exports.exchange = {}; 65 | load('exchange'); 66 | 67 | // alias exchanges 68 | exports.exchange.code = exports.exchange.authorizationCode; 69 | 70 | /** 71 | * Export errors. 72 | */ 73 | exports.OAuth2Error = require('./errors/oauth2error'); 74 | exports.AuthorizationError = require('./errors/authorizationerror'); 75 | exports.TokenError = require('./errors/tokenerror'); 76 | -------------------------------------------------------------------------------- /lib/resource-server.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2015,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | const SG = require('strong-globalize'); 8 | const g = SG(); 9 | const async = require('async'), 10 | oauth2Provider = require('./oauth2orize'), 11 | scopeValidator = require('./scope'), 12 | helpers = require('./oauth2-helper'), 13 | TokenError = require('./errors/tokenerror'), 14 | debug = require('debug')('loopback:oauth2'), 15 | passport = require('passport'), 16 | jwt = require('jws'), 17 | BearerStrategy = require('passport-http-bearer').Strategy, 18 | MacStrategy = require('./strategy/mac').Strategy; 19 | 20 | const clientInfo = helpers.clientInfo; 21 | const userInfo = helpers.userInfo; 22 | const isExpired = helpers.isExpired; 23 | 24 | module.exports = setupResourceServer; 25 | 26 | /** 27 | * Set up oAuth 2.0 strategies 28 | * @param {Object} app App instance 29 | * @param {Object} options Options 30 | * @param {Object} models oAuth 2.0 metadata models 31 | * @param {Boolean} jwt if jwt-bearer should be enabled 32 | * @returns {Function} 33 | */ 34 | function setupResourceServer(app, options, models) { 35 | function checkAccessToken(req, accessToken, done) { 36 | debug('Verifying access token %s', accessToken); 37 | models.accessTokens.find(accessToken, function(err, token) { 38 | if (err || !token) { 39 | return done(err); 40 | } 41 | 42 | debug('Access token found: %j', token); 43 | 44 | if (isExpired(token)) { 45 | return done(new TokenError(g.f('Access token is expired'), 46 | 'invalid_grant')); 47 | } 48 | 49 | const userId = token.userId || token.resourceOwner; 50 | const appId = token.appId || token.clientId; 51 | 52 | let user, app; 53 | async.parallel([ 54 | function lookupUser(done) { 55 | if (userId == null) { 56 | return process.nextTick(done); 57 | } 58 | models.users.find(userId, function(err, u) { 59 | if (err) { 60 | return done(err); 61 | } 62 | if (!u) { 63 | return done( 64 | new TokenError(g.f('Access token has invalid {{user id}}: %s', userId), 'invalid_grant') 65 | ); 66 | } 67 | debug('User found: %s', userInfo(u)); 68 | user = u; 69 | done(); 70 | }); 71 | }, 72 | function lookupApp(done) { 73 | if (appId == null) { 74 | return process.nextTick(done); 75 | } 76 | models.clients.find(appId, function(err, a) { 77 | if (err) { 78 | return done(err); 79 | } 80 | if (!a) { 81 | return done( 82 | new TokenError(g.f('Access token has invalid {{app id}}: %s', appId), 'invalid_grant') 83 | ); 84 | } 85 | debug('Client found: %s', clientInfo(a)); 86 | app = a; 87 | done(); 88 | }); 89 | }], function(err) { 90 | if (err) { 91 | return done(err); 92 | } 93 | if (options.addHttpHeaders) { 94 | let prefix = 'X-OAUTH2-'; 95 | if (typeof options.addHttpHeaders === 'string') { 96 | prefix = options.addHttpHeaders; 97 | } 98 | if (appId != null) { 99 | req.headers[prefix + 'CLIENT-ID'] = appId; 100 | } 101 | if (userId != null) { 102 | req.headers[prefix + 'USER-ID'] = userId; 103 | } 104 | } 105 | const authInfo = 106 | {accessToken: token, user: user, app: app, client: app}; 107 | done(null, user || {}, authInfo); 108 | }); 109 | }); 110 | } 111 | 112 | let verifyAccessToken = checkAccessToken; 113 | if (typeof options.checkAccessToken === 'function') { 114 | verifyAccessToken = options.checkAccessToken; 115 | } 116 | 117 | function accessTokenValidator(req, accessToken, done) { 118 | verifyAccessToken(req, accessToken, function(err, user, info) { 119 | if (!err && info) { 120 | req.accessToken = info.accessToken; 121 | } 122 | done(err, user, info); 123 | }); 124 | } 125 | 126 | /** 127 | * BearerStrategy 128 | * 129 | * This strategy is used to authenticate users based on an access token (aka a 130 | * bearer token). The user must have previously authorized a client 131 | * application, which is issued an access token to make requests on behalf of 132 | * the authorizing user. 133 | */ 134 | passport.use('loopback-oauth2-bearer', 135 | new BearerStrategy({passReqToCallback: true}, accessTokenValidator)); 136 | 137 | passport.use('loopback-oauth2-mac', 138 | new MacStrategy({passReqToCallback: true, jwtAlgorithm: 'HS256'}, 139 | function(req, accessToken, done) { 140 | accessTokenValidator(req, accessToken, function(err, user, info) { 141 | if (err || !user) { 142 | return done(err, user, info); 143 | } 144 | const client = info && info.client; 145 | const secret = client.clientSecret || client.restApiKey; 146 | try { 147 | const token = jwt.verify(accessToken, 'HS256', secret); 148 | debug('JWT token verified: %j', token); 149 | } catch (err) { 150 | debug('Fail to verify JWT: %j', err); 151 | done(err); 152 | } 153 | done(null, user, info); 154 | }); 155 | })); 156 | 157 | /** 158 | * Return the middleware chain to enforce oAuth 2.0 authentication and 159 | * authorization 160 | * @param {Object} [options] Options object 161 | * - scope 162 | * - jwt 163 | */ 164 | function authenticate(options) { 165 | options = options || {}; 166 | debug('Setting up authentication:', options); 167 | 168 | let authenticators = []; 169 | authenticators = [ 170 | passport.authenticate(['loopback-oauth2-bearer', 'loopback-oauth2-mac'], 171 | options)]; 172 | if (options.scopes || options.scope) { 173 | authenticators.push(scopeValidator(options)); 174 | } 175 | authenticators.push(oauth2Provider.errorHandler()); 176 | return authenticators; 177 | } 178 | 179 | return authenticate; 180 | } 181 | -------------------------------------------------------------------------------- /lib/scope.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2014,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | const SG = require('strong-globalize'); 8 | const g = SG(); 9 | const pathToRegexp = require('path-to-regexp'); 10 | const debug = require('debug')('loopback:oauth2:scope'); 11 | const oauth2Provider = require('./oauth2orize'); 12 | const helpers = require('./oauth2-helper'); 13 | 14 | function toLowerCase(m) { 15 | return m.toLowerCase(); 16 | } 17 | 18 | /** 19 | * Load the definition of scopes 20 | * 21 | * ```json 22 | * { 23 | * "scope1": [{"methods": "get", path: "/:user/profile"}, "/order"], 24 | * "scope2": [{"methods": "post", path: "/:user/profile"}] 25 | * } 26 | * ``` 27 | * @param {Object} scopes 28 | * @returns {Object} 29 | */ 30 | function loadScopes(scopes) { 31 | const scopeMapping = {}; 32 | if (typeof scopes === 'object' && !Array.isArray(scopes)) { 33 | for (const s in scopes) { 34 | const routes = []; 35 | const entries = scopes[s]; 36 | debug('Scope: %s routes: %j', s, entries); 37 | if (Array.isArray(entries)) { 38 | for (let j = 0, k = entries.length; j < k; j++) { 39 | const route = entries[j]; 40 | if (typeof route === 'string') { 41 | routes.push({methods: ['all'], path: route, 42 | regexp: pathToRegexp(route, [], {end: false})}); 43 | } else { 44 | let methods = helpers.normalizeList(route.methods); 45 | if (methods.length === 0) { 46 | methods.push('all'); 47 | } 48 | methods = methods.map(toLowerCase); 49 | routes.push({methods: methods, 50 | path: route.path, 51 | regexp: pathToRegexp(route.path, [], {end: false})}); 52 | } 53 | } 54 | } else { 55 | debug('Routes must be an array: %j', entries); 56 | } 57 | scopeMapping[s] = routes; 58 | } 59 | } else if (typeof scopes === 'string' || Array.isArray(scopes)) { 60 | scopes = helpers.normalizeList(scopes); 61 | for (let i = 0, n = scopes.length; i < n; i++) { 62 | scopeMapping[scopes[i]] = [ 63 | {methods: 'all', path: '/.+', regexp: /\/.+/}, 64 | ]; 65 | } 66 | } 67 | return scopeMapping; 68 | } 69 | 70 | function findMatchedScopes(req, scopeMapping) { 71 | const matchedScopes = []; 72 | const method = req.method.toLowerCase(); 73 | let url = req.originalUrl; 74 | for (const s in scopeMapping) { 75 | const routes = scopeMapping[s]; 76 | for (let i = 0, n = routes.length; i < n; i++) { 77 | const route = routes[i]; 78 | if (route.methods.indexOf('all') !== -1 || 79 | route.methods.indexOf(method) !== -1) { 80 | debug('url: %s, regexp: %s', url, route.regexp); 81 | const index = url.indexOf('?'); 82 | if (index !== -1) { 83 | url = url.substring(0, index); 84 | } 85 | if (route.regexp.test(url)) { 86 | matchedScopes.push(s); 87 | } 88 | } 89 | } 90 | } 91 | return matchedScopes; 92 | } 93 | 94 | /** 95 | * Validate if the oAuth 2 scope is satisfied 96 | * 97 | * @param {Object} options Options object 98 | * @returns {validateScope} 99 | */ 100 | module.exports = function(options) { 101 | const configuredScopes = options.checkScopes || options.scopes || options.scope; 102 | let checkScopes; 103 | if (typeof configuredScopes === 'function') { 104 | checkScopes = configuredScopes; 105 | } else { 106 | checkScopes = function(req, tokenScopes, cb) { 107 | const scopeMapping = loadScopes(configuredScopes); 108 | debug('Scope mapping: ', scopeMapping); 109 | const allowedScopes = findMatchedScopes(req, scopeMapping); 110 | debug('Allowed scopes: ', allowedScopes); 111 | if (helpers.isScopeAllowed(allowedScopes, tokenScopes)) { 112 | cb(); 113 | } else { 114 | debug('Insufficient scope: ', tokenScopes); 115 | cb(new oauth2Provider.TokenError(g.f( 116 | 'Insufficient scope' 117 | ), 'insufficient_scope', null, 403)); 118 | } 119 | }; 120 | } 121 | return function validateScope(req, res, next) { 122 | const scopes = req.accessToken && req.accessToken.scopes; 123 | debug('Scopes of the access token: ', scopes); 124 | checkScopes(req, scopes, next); 125 | }; 126 | }; 127 | -------------------------------------------------------------------------------- /lib/strategy/jwt-bearer/index.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2014,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | 8 | /** 9 | * Module dependencies. 10 | */ 11 | const Strategy = require('./strategy'); 12 | 13 | /** 14 | * Expose `Strategy` directly from package. 15 | */ 16 | exports = module.exports = Strategy; 17 | 18 | /** 19 | * Expose constructors. 20 | */ 21 | exports.Strategy = Strategy; 22 | -------------------------------------------------------------------------------- /lib/strategy/mac/index.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2015,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | /** 8 | * Module dependencies. 9 | */ 10 | const Strategy = require('./strategy'); 11 | 12 | /** 13 | * Expose `Strategy` directly from package. 14 | */ 15 | exports = module.exports = Strategy; 16 | 17 | /** 18 | * Export constructors. 19 | */ 20 | exports.Strategy = Strategy; 21 | -------------------------------------------------------------------------------- /lib/strategy/mac/strategy.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2015,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | /** 8 | * Module dependencies. 9 | */ 10 | const SG = require('strong-globalize'); 11 | const g = SG(); 12 | const passport = require('passport-strategy'), 13 | util = require('util'), 14 | MACGenerator = require('../../mac-token'); 15 | 16 | /** 17 | * Creates an instance of `Strategy`. 18 | * 19 | * The HTTP MAC authentication strategy authenticates requests based on 20 | * a mac token contained in the `Authorization` header field, `access_token` 21 | * body parameter, or `access_token` query parameter. 22 | * 23 | * Applications must supply a `verify` callback, for which the function 24 | * signature is: 25 | * 26 | * function(token, done) { ... } 27 | * 28 | * `token` is the mac token provided as a credential. The verify callback 29 | * is responsible for finding the user who posesses the token, and invoking 30 | * `done` with the following arguments: 31 | * 32 | * done(err, user, info); 33 | * 34 | * If the token is not valid, `user` should be set to `false` to indicate an 35 | * authentication failure. Additional token `info` can optionally be passed as 36 | * a third argument, which will be set by Passport at `req.authInfo`, where it 37 | * can be used by later middleware for access control. This is typically used 38 | * to pass any scope associated with the token. 39 | * 40 | * Options: 41 | * 42 | * - `algorithm` mac key 43 | * - `key` mac key 44 | * 45 | * Examples: 46 | * 47 | * passport.use(new MACStrategy( 48 | * function(token, done) { 49 | * User.findByToken({ token: token }, function (err, user) { 50 | * if (err) { return done(err); } 51 | * if (!user) { return done(null, false); } 52 | * return done(null, user, { scope: 'read' }); 53 | * }); 54 | * } 55 | * )); 56 | * 57 | * For further details on HTTP MAC authentication, refer to [OAuth 2.0 Message Authentication Code (MAC) Tokens](https://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-05) 58 | * 59 | * @constructor 60 | * @param {Object} [options] 61 | * @param {Function} verify 62 | * @api public 63 | */ 64 | function Strategy(options, verify) { 65 | if (typeof options === 'function') { 66 | verify = options; 67 | options = {}; 68 | } 69 | if (!verify) { 70 | throw new TypeError(g.f('{{MACStrategy}} requires a verify callback')); 71 | } 72 | 73 | passport.Strategy.call(this); 74 | this.name = 'oauth2-mac'; 75 | this._verify = verify; 76 | this._algorithm = options.algorithm || 'sha256'; 77 | this._passReqToCallback = options.passReqToCallback; 78 | this._macGenerator = new MACGenerator(this._algorithm); 79 | } 80 | 81 | /** 82 | * Inherit from `passport.Strategy`. 83 | */ 84 | util.inherits(Strategy, passport.Strategy); 85 | 86 | /** 87 | * Authenticate request based on the contents of a HTTP MAC authorization 88 | * header. 89 | * 90 | * @param {Object} req 91 | * @api protected 92 | */ 93 | Strategy.prototype.authenticate = function(req) { 94 | const authorizationHeader = req.get('authorization'); 95 | if (!(authorizationHeader && authorizationHeader.indexOf('MAC ') === 0)) { 96 | return this.fail(); 97 | } 98 | 99 | const token = this._macGenerator.validate(req); 100 | 101 | if (!token) { 102 | return this.fail(this._challenge(g.f('Invalid {{MAC}} token'))); 103 | } 104 | 105 | const self = this; 106 | 107 | function verified(err, user, info) { 108 | if (err) { 109 | return self.error(err); 110 | } 111 | if (!user) { 112 | if (typeof info === 'string') { 113 | info = {message: info}; 114 | } 115 | info = info || {}; 116 | return self.fail(self._challenge('invalid_token', info.message)); 117 | } 118 | self.success(user, info); 119 | } 120 | 121 | if (self._passReqToCallback) { 122 | this._verify(req, token, verified); 123 | } else { 124 | this._verify(token, verified); 125 | } 126 | }; 127 | 128 | /** 129 | * Build authentication challenge. 130 | * 131 | * @api private 132 | */ 133 | Strategy.prototype._challenge = function(err) { 134 | let challenge = 'MAC '; 135 | 136 | if (err) { 137 | challenge += ' error="' + err + '"'; 138 | } 139 | 140 | return challenge; 141 | }; 142 | 143 | /** 144 | * Expose `Strategy`. 145 | */ 146 | module.exports = Strategy; 147 | -------------------------------------------------------------------------------- /lib/unorderedlist.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2012,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | /** 8 | * `UnorderedList` constructor. 9 | * 10 | * @api public 11 | */ 12 | function UnorderedList(items) { 13 | if (typeof items == 'string') { 14 | items = items.split(' '); 15 | } 16 | this._items = items || []; 17 | this.__defineGetter__('length', this._length); 18 | } 19 | 20 | /** 21 | * Check if list is equal to `other` list. 22 | * 23 | * @param {UnorderedList} other 24 | * @return {Boolean} 25 | * @api public 26 | */ 27 | UnorderedList.prototype.equalTo = function(other) { 28 | if (!(other instanceof UnorderedList)) { 29 | other = new UnorderedList(other); 30 | } 31 | 32 | if (this.length != other.length) { return false; } 33 | for (let i = 0, len = this._items.length; i < len; i++) { 34 | const item = this._items[i]; 35 | if (other._items.indexOf(item) == -1) { 36 | return false; 37 | } 38 | } 39 | return true; 40 | }; 41 | 42 | /** 43 | * Check if list contains `val` 44 | * 45 | * @param {String} val 46 | * @return {Boolean} 47 | * @api public 48 | */ 49 | UnorderedList.prototype.contains = function(val) { 50 | return this._items.indexOf(val) != -1; 51 | }; 52 | 53 | /** 54 | * Check if list contains any element in `arr` 55 | * 56 | * @param {Array} arr 57 | * @return {Boolean} 58 | * @api public 59 | */ 60 | UnorderedList.prototype.containsAny = function(arr) { 61 | for (let i = 0, len = arr.length; i < len; i++) { 62 | if (this._items.indexOf(arr[i]) != -1) { return true; } 63 | } 64 | return false; 65 | }; 66 | 67 | /** 68 | * String representation of list. 69 | * 70 | * @return {String} 71 | * @api private 72 | */ 73 | UnorderedList.prototype.toString = function() { 74 | return this._items.join(' '); 75 | }; 76 | 77 | /** 78 | * Length of list. 79 | * 80 | * @return {Number} 81 | * @api private 82 | */ 83 | UnorderedList.prototype._length = function() { 84 | return this._items.length; 85 | }; 86 | 87 | /** 88 | * Expose `UnorderedList`. 89 | */ 90 | module.exports = UnorderedList; 91 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2012,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | exports.merge = require('utils-merge'); 8 | exports.uid = require('uid2'); 9 | -------------------------------------------------------------------------------- /loopback-oauth2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strongloop/loopback-component-oauth2/c87e35633d7e7aaef1265340827ba0fa4cf53cc3/loopback-oauth2.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "loopback-component-oauth2", 3 | "version": "3.2.0", 4 | "description": "OAuth 2.0 provider for LoopBack", 5 | "engines": { 6 | "node": ">= 6" 7 | }, 8 | "keywords": [ 9 | "StrongLoop", 10 | "LoopBack", 11 | "oauth", 12 | "oauth2", 13 | "passport", 14 | "authentication", 15 | "authorization", 16 | "gateway", 17 | "api", 18 | "loopback-component" 19 | ], 20 | "loopback-component": {}, 21 | "repository": { 22 | "type": "git", 23 | "url": "git://github.com/strongloop/loopback-component-oauth2.git" 24 | }, 25 | "bugs": { 26 | "url": "http://github.com/strongloop/loopback-component-oauth2/issues" 27 | }, 28 | "main": "./lib", 29 | "dependencies": { 30 | "async": "^1.5.2", 31 | "body-parser": "^1.15.2", 32 | "connect-ensure-login": "^0.1.1", 33 | "debug": "^2.2.0", 34 | "jws": "^3.0.0", 35 | "passport": "^0.3.2", 36 | "passport-http": "^0.3.0", 37 | "passport-http-bearer": "^1.0.1", 38 | "passport-local": "^1.0.0", 39 | "passport-oauth2-client-password": "^0.1.2", 40 | "passport-strategy": "^1.0.0", 41 | "path-to-regexp": "^1.2.0", 42 | "pkginfo": "^0.4.0", 43 | "strong-globalize": "^2.6.2", 44 | "uid2": "^0.0.3", 45 | "utils-merge": "^1.0.0" 46 | }, 47 | "devDependencies": { 48 | "chai": "^3.5.0", 49 | "chai-connect-middleware": "^0.3.1", 50 | "chai-oauth2orize-grant": "^0.2.0", 51 | "eslint": "^4.18.2", 52 | "eslint-config-loopback": "^13.1.0", 53 | "loopback": "^3.0.0", 54 | "mocha": "^5.2.0", 55 | "vows": "^0.8.1" 56 | }, 57 | "scripts": { 58 | "test": "mocha --reporter spec --require test/bootstrap/node test/*.test.js test/**/*.test.js", 59 | "lint": "eslint .", 60 | "posttest": "npm run lint" 61 | }, 62 | "license": "MIT", 63 | "author": "IBM Corp." 64 | } 65 | -------------------------------------------------------------------------------- /support/mk/coveralls.mk: -------------------------------------------------------------------------------- 1 | COVERALLS ?= coveralls 2 | 3 | submit-istanbul-lcov-to-coveralls: 4 | cat $(ISTANBUL_LCOV_INFO_PATH) | $(COVERALLS) 5 | 6 | 7 | .PHONY: submit-istanbul-lcov-to-coveralls 8 | -------------------------------------------------------------------------------- /support/mk/istanbul.mk: -------------------------------------------------------------------------------- 1 | ISTANBUL ?= istanbul 2 | ISTANBUL_OUT ?= ./reports/coverage 3 | ISTANBUL_REPORT ?= lcov 4 | ISTANBUL_LCOV_INFO_PATH ?= $(ISTANBUL_OUT)/lcov.info 5 | ISTANBUL_HTML_REPORT_PATH ?= $(ISTANBUL_OUT)/lcov-report/index.html 6 | 7 | 8 | test-istanbul-mocha: node_modules 9 | NODE_PATH=$(NODE_PATH_TEST) \ 10 | $(ISTANBUL) cover \ 11 | --dir $(ISTANBUL_OUT) --report $(ISTANBUL_REPORT) \ 12 | $(_MOCHA) -- \ 13 | --reporter $(MOCHA_REPORTER) \ 14 | --require $(MOCHA_REQUIRE) \ 15 | $(TESTS) 16 | 17 | view-istanbul-report: 18 | open $(ISTANBUL_HTML_REPORT_PATH) 19 | 20 | 21 | .PHONY: test-istanbul-mocha view-istanbul-report 22 | -------------------------------------------------------------------------------- /support/mk/jshint.mk: -------------------------------------------------------------------------------- 1 | JSHINT ?= jshint 2 | 3 | lint-jshint: 4 | $(JSHINT) $(SOURCES) 5 | 6 | lint-tests-jshint: 7 | $(JSHINT) $(TESTS) 8 | 9 | 10 | .PHONY: lint-jshint lint-tests-jshint 11 | -------------------------------------------------------------------------------- /support/mk/mocha.mk: -------------------------------------------------------------------------------- 1 | MOCHA ?= ./node_modules/.bin/mocha 2 | _MOCHA ?= ./node_modules/.bin/_mocha 3 | MOCHA_REPORTER ?= spec 4 | MOCHA_REQUIRE ?= ./test/bootstrap/node 5 | 6 | test-mocha: node_modules 7 | NODE_PATH=$(NODE_PATH_TEST) \ 8 | $(MOCHA) \ 9 | --reporter $(MOCHA_REPORTER) \ 10 | --require $(MOCHA_REQUIRE) \ 11 | $(TESTS) 12 | 13 | 14 | .PHONY: test-mocha 15 | -------------------------------------------------------------------------------- /support/mk/node.mk: -------------------------------------------------------------------------------- 1 | node_modules: 2 | npm install 3 | 4 | clobber-node: 5 | rm -rf node_modules 6 | 7 | 8 | .PHONY: clobber-node 9 | -------------------------------------------------------------------------------- /support/mk/notes.mk: -------------------------------------------------------------------------------- 1 | NOTES ?= 'TODO|FIXME' 2 | 3 | notes: 4 | grep -Ern $(NOTES) $(SOURCES) $(TESTS) 5 | 6 | 7 | .PHONY: notes 8 | -------------------------------------------------------------------------------- /support/mk/testling.mk: -------------------------------------------------------------------------------- 1 | TESTLING ?= testling 2 | 3 | test-testling: node_modules 4 | $(TESTLING) 5 | 6 | 7 | .PHONY: test-testling 8 | -------------------------------------------------------------------------------- /test/bootstrap/node.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2013,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | const chai = require('chai'); 8 | 9 | chai.use(require('chai-connect-middleware')); 10 | chai.use(require('chai-oauth2orize-grant')); 11 | 12 | global.expect = chai.expect; 13 | -------------------------------------------------------------------------------- /test/errors/authorizationerror.test.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2013,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | const expect = require('chai').expect; 8 | const OAuth2Error = require('../../lib/errors/oauth2error'), 9 | AuthorizationError = require('../../lib/errors/authorizationerror'); 10 | 11 | describe('AuthorizationError', function() { 12 | describe('constructed without a message', function() { 13 | const err = new AuthorizationError(); 14 | 15 | it('should have default properties', function() { 16 | expect(err.message).to.be.undefined; 17 | expect(err.code).to.equal('server_error'); 18 | expect(err.uri).to.be.undefined; 19 | expect(err.status).to.equal(500); 20 | }); 21 | 22 | it('should format correctly', function() { 23 | // expect(err.toString()).to.equal('AuthorizationError'); 24 | expect(err.toString().indexOf('AuthorizationError')).to.equal(0); 25 | }); 26 | 27 | it('should inherits from OAuth2Error and Error', function() { 28 | expect(err).to.be.instanceof(OAuth2Error); 29 | expect(err).to.be.instanceof(Error); 30 | }); 31 | }); 32 | 33 | describe('constructed with a message', function() { 34 | const err = new AuthorizationError('Invalid return URI'); 35 | 36 | it('should have default properties', function() { 37 | expect(err.message).to.equal('Invalid return URI'); 38 | expect(err.code).to.equal('server_error'); 39 | expect(err.uri).to.be.undefined; 40 | expect(err.status).to.equal(500); 41 | }); 42 | 43 | it('should format correctly', function() { 44 | expect(err.toString()).to.equal('AuthorizationError: Invalid return URI'); 45 | }); 46 | }); 47 | 48 | describe('constructed with a message and invalid_request code', function() { 49 | const err = new AuthorizationError('Invalid request', 'invalid_request'); 50 | 51 | it('should have default properties', function() { 52 | expect(err.message).to.equal('Invalid request'); 53 | expect(err.code).to.equal('invalid_request'); 54 | expect(err.uri).to.be.undefined; 55 | expect(err.status).to.equal(400); 56 | }); 57 | }); 58 | 59 | describe('constructed with a message and unauthorized_client code', function() { 60 | const err = new AuthorizationError('Unauthorized client', 'unauthorized_client'); 61 | 62 | it('should have default properties', function() { 63 | expect(err.message).to.equal('Unauthorized client'); 64 | expect(err.code).to.equal('unauthorized_client'); 65 | expect(err.uri).to.be.undefined; 66 | expect(err.status).to.equal(403); 67 | }); 68 | }); 69 | 70 | describe('constructed with a message and access_denied code', function() { 71 | const err = new AuthorizationError('Access denied', 'access_denied'); 72 | 73 | it('should have default properties', function() { 74 | expect(err.message).to.equal('Access denied'); 75 | expect(err.code).to.equal('access_denied'); 76 | expect(err.uri).to.be.undefined; 77 | expect(err.status).to.equal(403); 78 | }); 79 | }); 80 | 81 | describe('constructed with a message and unsupported_response_type code', function() { 82 | const err = new AuthorizationError('Unsupported response type', 'unsupported_response_type'); 83 | 84 | it('should have default properties', function() { 85 | expect(err.message).to.equal('Unsupported response type'); 86 | expect(err.code).to.equal('unsupported_response_type'); 87 | expect(err.uri).to.be.undefined; 88 | expect(err.status).to.equal(400); 89 | }); 90 | }); 91 | 92 | describe('constructed with a message and invalid_scope code', function() { 93 | const err = new AuthorizationError('Invalid scope', 'invalid_scope'); 94 | 95 | it('should have default properties', function() { 96 | expect(err.message).to.equal('Invalid scope'); 97 | expect(err.code).to.equal('invalid_scope'); 98 | expect(err.uri).to.be.undefined; 99 | expect(err.status).to.equal(400); 100 | }); 101 | }); 102 | 103 | describe('constructed with a message and temporarily_unavailable code', function() { 104 | const err = new AuthorizationError('Temporarily unavailable', 'temporarily_unavailable'); 105 | 106 | it('should have default properties', function() { 107 | expect(err.message).to.equal('Temporarily unavailable'); 108 | expect(err.code).to.equal('temporarily_unavailable'); 109 | expect(err.uri).to.be.undefined; 110 | expect(err.status).to.equal(503); 111 | }); 112 | }); 113 | 114 | describe('constructed with a message, code, uri and status', function() { 115 | const err = new AuthorizationError('Payment required', 'payment_required', 'http://www.example.com/oauth/help', 402); 116 | 117 | it('should have default properties', function() { 118 | expect(err.message).to.equal('Payment required'); 119 | expect(err.code).to.equal('payment_required'); 120 | expect(err.uri).to.equal('http://www.example.com/oauth/help'); 121 | expect(err.status).to.equal(402); 122 | }); 123 | 124 | it('should format correctly', function() { 125 | expect(err.toString()).to.equal('AuthorizationError: Payment required'); 126 | }); 127 | }); 128 | }); 129 | -------------------------------------------------------------------------------- /test/errors/badrequesterror.test.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2013,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | const BadRequestError = require('../../lib/errors/badrequesterror'); 8 | const expect = require('chai').expect; 9 | 10 | describe('BadRequestError', function() { 11 | describe('constructed without a message', function() { 12 | const err = new BadRequestError(); 13 | 14 | it('should have default properties', function() { 15 | expect(err.message).to.be.undefined; 16 | }); 17 | 18 | it('should format correctly', function() { 19 | // expect(err.toString()).to.equal('BadRequestError'); 20 | expect(err.toString().indexOf('BadRequestError')).to.equal(0); 21 | }); 22 | 23 | it('should have status', function() { 24 | expect(err.status).to.equal(400); 25 | }); 26 | 27 | it('should inherits from Error', function() { 28 | expect(err).to.be.instanceof(Error); 29 | }); 30 | }); 31 | 32 | describe('constructed with a message', function() { 33 | const err = new BadRequestError('Bad request'); 34 | 35 | it('should have default properties', function() { 36 | expect(err.message).to.equal('Bad request'); 37 | }); 38 | 39 | it('should format correctly', function() { 40 | expect(err.toString()).to.equal('BadRequestError: Bad request'); 41 | }); 42 | 43 | it('should have status', function() { 44 | expect(err.status).to.equal(400); 45 | }); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /test/errors/forbiddenerror.test.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2013,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | const ForbiddenError = require('../../lib/errors/forbiddenerror'); 8 | const expect = require('chai').expect; 9 | 10 | describe('ForbiddenError', function() { 11 | describe('constructed without a message', function() { 12 | const err = new ForbiddenError(); 13 | 14 | it('should have default properties', function() { 15 | expect(err.message).to.be.undefined; 16 | }); 17 | 18 | it('should format correctly', function() { 19 | // expect(err.toString()).to.equal('ForbiddenError'); 20 | expect(err.toString().indexOf('ForbiddenError')).to.equal(0); 21 | }); 22 | 23 | it('should have status', function() { 24 | expect(err.status).to.equal(403); 25 | }); 26 | 27 | it('should inherits from Error', function() { 28 | expect(err).to.be.instanceof(Error); 29 | }); 30 | }); 31 | 32 | describe('constructed with a message', function() { 33 | const err = new ForbiddenError('Forbidden'); 34 | 35 | it('should have default properties', function() { 36 | expect(err.message).to.equal('Forbidden'); 37 | }); 38 | 39 | it('should format correctly', function() { 40 | expect(err.toString()).to.equal('ForbiddenError: Forbidden'); 41 | }); 42 | 43 | it('should have status', function() { 44 | expect(err.status).to.equal(403); 45 | }); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /test/errors/tokenerror.test.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2013,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | const expect = require('chai').expect; 8 | const OAuth2Error = require('../../lib/errors/oauth2error'), 9 | TokenError = require('../../lib/errors/tokenerror'); 10 | 11 | describe('TokenError', function() { 12 | describe('constructed without a message', function() { 13 | const err = new TokenError(); 14 | 15 | it('should have default properties', function() { 16 | expect(err.message).to.be.undefined; 17 | expect(err.code).to.equal('server_error'); 18 | expect(err.uri).to.be.undefined; 19 | expect(err.status).to.equal(500); 20 | }); 21 | 22 | it('should format correctly', function() { 23 | // expect(err.toString()).to.equal('AuthorizationError'); 24 | expect(err.toString().indexOf('TokenError')).to.equal(0); 25 | }); 26 | 27 | it('should inherits from OAuth2Error and Error', function() { 28 | expect(err).to.be.instanceof(OAuth2Error); 29 | expect(err).to.be.instanceof(Error); 30 | }); 31 | }); 32 | 33 | describe('constructed with a message', function() { 34 | const err = new TokenError('Invalid return URI'); 35 | 36 | it('should have default properties', function() { 37 | expect(err.message).to.equal('Invalid return URI'); 38 | expect(err.code).to.equal('server_error'); 39 | expect(err.uri).to.be.undefined; 40 | expect(err.status).to.equal(500); 41 | }); 42 | 43 | it('should format correctly', function() { 44 | expect(err.toString()).to.equal('TokenError: Invalid return URI'); 45 | }); 46 | }); 47 | 48 | describe('constructed with a message and invalid_request code', function() { 49 | const err = new TokenError('Invalid request', 'invalid_request'); 50 | 51 | it('should have default properties', function() { 52 | expect(err.message).to.equal('Invalid request'); 53 | expect(err.code).to.equal('invalid_request'); 54 | expect(err.uri).to.be.undefined; 55 | expect(err.status).to.equal(400); 56 | }); 57 | }); 58 | 59 | describe('constructed with a message and invalid_client code', function() { 60 | const err = new TokenError('Invalid client', 'invalid_client'); 61 | 62 | it('should have default properties', function() { 63 | expect(err.message).to.equal('Invalid client'); 64 | expect(err.code).to.equal('invalid_client'); 65 | expect(err.uri).to.be.undefined; 66 | expect(err.status).to.equal(401); 67 | }); 68 | }); 69 | 70 | describe('constructed with a message and invalid_grant code', function() { 71 | const err = new TokenError('Invalid grant', 'invalid_grant'); 72 | 73 | it('should have default properties', function() { 74 | expect(err.message).to.equal('Invalid grant'); 75 | expect(err.code).to.equal('invalid_grant'); 76 | expect(err.uri).to.be.undefined; 77 | expect(err.status).to.equal(403); 78 | }); 79 | }); 80 | 81 | describe('constructed with a message and unauthorized_client code', function() { 82 | const err = new TokenError('Unauthorized client', 'unauthorized_client'); 83 | 84 | it('should have default properties', function() { 85 | expect(err.message).to.equal('Unauthorized client'); 86 | expect(err.code).to.equal('unauthorized_client'); 87 | expect(err.uri).to.be.undefined; 88 | expect(err.status).to.equal(403); 89 | }); 90 | }); 91 | 92 | describe('constructed with a message and unsupported_grant_type code', function() { 93 | const err = new TokenError('Unsupported grant type', 'unsupported_grant_type'); 94 | 95 | it('should have default properties', function() { 96 | expect(err.message).to.equal('Unsupported grant type'); 97 | expect(err.code).to.equal('unsupported_grant_type'); 98 | expect(err.uri).to.be.undefined; 99 | expect(err.status).to.equal(400); 100 | }); 101 | }); 102 | 103 | describe('constructed with a message and invalid_scope code', function() { 104 | const err = new TokenError('Invalid scope', 'invalid_scope'); 105 | 106 | it('should have default properties', function() { 107 | expect(err.message).to.equal('Invalid scope'); 108 | expect(err.code).to.equal('invalid_scope'); 109 | expect(err.uri).to.be.undefined; 110 | expect(err.status).to.equal(400); 111 | }); 112 | }); 113 | 114 | describe('constructed with a message, code, uri and status', function() { 115 | const err = new TokenError('Payment required', 'payment_required', 'http://www.example.com/oauth/help', 402); 116 | 117 | it('should have default properties', function() { 118 | expect(err.message).to.equal('Payment required'); 119 | expect(err.code).to.equal('payment_required'); 120 | expect(err.uri).to.equal('http://www.example.com/oauth/help'); 121 | expect(err.status).to.equal(402); 122 | }); 123 | 124 | it('should format correctly', function() { 125 | expect(err.toString()).to.equal('TokenError: Payment required'); 126 | }); 127 | }); 128 | }); 129 | -------------------------------------------------------------------------------- /test/middleware/token.test.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2013,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | /* global describe, it, expect, before */ 7 | /* jshint camelcase: false */ 8 | 9 | 'use strict'; 10 | const chai = require('chai'), 11 | token = require('../../lib/middleware/token'), 12 | Server = require('../../lib/server'); 13 | 14 | describe('token', function() { 15 | const server = new Server(); 16 | server.exchange('authorization_code', function(req, res, next) { 17 | if (req.body.code == 'abc123') { 18 | const json = JSON.stringify({token_type: 'bearer', access_token: 'aaa-111-ccc'}); 19 | return res.end(json); 20 | } 21 | return next(new Error('something went wrong while exchanging grant')); 22 | }); 23 | server.exchange('next-error', function(req, res, next) { 24 | next(new Error('something went wrong')); 25 | }); 26 | 27 | it('should be named token', function() { 28 | expect(token(server).name).to.equal('token'); 29 | }); 30 | 31 | it('should throw if constructed without a server argument', function() { 32 | expect(function() { 33 | token(); 34 | }).to.throw(TypeError, 'oauth2orize.token middleware requires a server argument'); 35 | }); 36 | 37 | describe('handling a request for an access token', function() { 38 | let response; 39 | 40 | before(function(done) { 41 | chai.connect.use(token(server)) 42 | .req(function(req) { 43 | req.body = {grant_type: 'authorization_code', code: 'abc123'}; 44 | }) 45 | .end(function(res) { 46 | response = res; 47 | done(); 48 | }) 49 | .dispatch(); 50 | }); 51 | 52 | it('should respond', function() { 53 | expect(response.body).to.equal('{"token_type":"bearer","access_token":"aaa-111-ccc"}'); 54 | }); 55 | }); 56 | 57 | describe('handling a request for an access token with unsupported grant type', function() { 58 | let err; 59 | 60 | before(function(done) { 61 | chai.connect.use(token(server)) 62 | .req(function(req) { 63 | req.body = {grant_type: 'foo', code: 'abc123'}; 64 | }) 65 | .next(function(e) { 66 | err = e; 67 | done(); 68 | }) 69 | .dispatch(); 70 | }); 71 | 72 | it('should error', function() { 73 | expect(err).to.be.an.instanceOf(Error); 74 | expect(err.constructor.name).to.equal('TokenError'); 75 | expect(err.message).to.equal('Unsupported grant type: foo'); 76 | expect(err.code).to.equal('unsupported_grant_type'); 77 | }); 78 | }); 79 | 80 | describe('encountering an error while exchanging grant', function() { 81 | let err; 82 | 83 | before(function(done) { 84 | chai.connect.use(token(server)) 85 | .req(function(req) { 86 | req.body = {grant_type: 'next-error', code: 'abc123'}; 87 | }) 88 | .next(function(e) { 89 | err = e; 90 | done(); 91 | }) 92 | .dispatch(); 93 | }); 94 | 95 | it('should error', function() { 96 | expect(err).to.be.an.instanceOf(Error); 97 | expect(err.message).to.equal('something went wrong'); 98 | }); 99 | }); 100 | }); 101 | -------------------------------------------------------------------------------- /test/package.test.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2013,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | const oauth2orize = require('..').oauth2orize, 8 | Server = require('../lib/server'); 9 | const expect = require('chai').expect; 10 | 11 | describe('oauth2orize', function() { 12 | it('should export createServer', function() { 13 | expect(oauth2orize).to.be.a('function'); 14 | expect(oauth2orize.createServer).to.be.a('function'); 15 | expect(oauth2orize).to.equal(oauth2orize.createServer); 16 | }); 17 | 18 | it('should export middleware', function() { 19 | expect(oauth2orize.errorHandler).to.be.a('function'); 20 | }); 21 | 22 | it('should export grants', function() { 23 | expect(oauth2orize.grant).to.be.an('object'); 24 | expect(oauth2orize.grant.code).to.be.a('function'); 25 | expect(oauth2orize.grant.token).to.be.a('function'); 26 | }); 27 | 28 | it('should export aliased grants', function() { 29 | expect(oauth2orize.grant.authorizationCode).to.equal(oauth2orize.grant.code); 30 | expect(oauth2orize.grant.implicit).to.equal(oauth2orize.grant.token); 31 | }); 32 | 33 | it('should export exchanges', function() { 34 | expect(oauth2orize.exchange).to.be.an('object'); 35 | expect(oauth2orize.exchange.authorizationCode).to.be.a('function'); 36 | expect(oauth2orize.exchange.clientCredentials).to.be.a('function'); 37 | expect(oauth2orize.exchange.password).to.be.a('function'); 38 | expect(oauth2orize.exchange.refreshToken).to.be.a('function'); 39 | }); 40 | 41 | it('should export aliased exchanges', function() { 42 | expect(oauth2orize.exchange.code).to.equal(oauth2orize.exchange.authorizationCode); 43 | }); 44 | 45 | it('should export Error constructors', function() { 46 | expect(oauth2orize.OAuth2Error).to.be.a('function'); 47 | expect(oauth2orize.AuthorizationError).to.be.a('function'); 48 | expect(oauth2orize.TokenError).to.be.a('function'); 49 | }); 50 | 51 | describe('.createServer', function() { 52 | it('should return a server', function() { 53 | const s = oauth2orize.createServer(); 54 | expect(s).to.be.an.instanceOf(Server); 55 | }); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /test/passport-http-bearer/index-test.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2012,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | const vows = require('vows'); 8 | const assert = require('assert'); 9 | const util = require('util'); 10 | const bearer = require('../../lib/passport-http-bearer/index'); 11 | 12 | vows.describe('passport-http-bearer').addBatch({ 13 | 14 | 'module': { 15 | 'should report a version': function(x) { 16 | assert.isString(bearer.version); 17 | }, 18 | }, 19 | 20 | }).export(module); 21 | -------------------------------------------------------------------------------- /test/server.grant.test.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2013,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | const Server = require('../lib/server'); 8 | const expect = require('chai').expect; 9 | 10 | describe('Server', function() { 11 | describe('registering a grant module', function() { 12 | const server = new Server(); 13 | const mod = {}; 14 | mod.name = 'foo'; 15 | mod.request = function(req) {}; 16 | mod.response = function(txn, res, next) {}; 17 | server.grant(mod); 18 | 19 | it('should have one request parser', function() { 20 | expect(server._reqParsers).to.have.length(1); 21 | const parser = server._reqParsers[0]; 22 | expect(parser.type.toString()).to.equal('foo'); 23 | expect(parser.handle).to.be.a('function'); 24 | expect(parser.handle).to.have.length(1); 25 | }); 26 | 27 | it('should have one response handler', function() { 28 | expect(server._resHandlers).to.have.length(1); 29 | const handler = server._resHandlers[0]; 30 | expect(handler.type.toString()).to.equal('foo'); 31 | expect(handler.handle).to.be.a('function'); 32 | expect(handler.handle).to.have.length(3); 33 | }); 34 | }); 35 | 36 | describe('registering a grant module by type', function() { 37 | const server = new Server(); 38 | const mod = {}; 39 | mod.name = 'foo'; 40 | mod.request = function(req) {}; 41 | mod.response = function(txn, res, next) {}; 42 | server.grant('bar', mod); 43 | 44 | it('should have one request parser', function() { 45 | expect(server._reqParsers).to.have.length(1); 46 | const parser = server._reqParsers[0]; 47 | expect(parser.type.toString()).to.equal('bar'); 48 | expect(parser.handle).to.be.a('function'); 49 | expect(parser.handle).to.have.length(1); 50 | }); 51 | 52 | it('should have one response handler', function() { 53 | expect(server._resHandlers).to.have.length(1); 54 | const handler = server._resHandlers[0]; 55 | expect(handler.type.toString()).to.equal('bar'); 56 | expect(handler.handle).to.be.a('function'); 57 | expect(handler.handle).to.have.length(3); 58 | }); 59 | }); 60 | 61 | describe('registering a grant parsing function by type', function() { 62 | const server = new Server(); 63 | const mod = {}; 64 | server.grant('foo', function(req) {}); 65 | 66 | it('should have one request parser', function() { 67 | expect(server._reqParsers).to.have.length(1); 68 | const parser = server._reqParsers[0]; 69 | expect(parser.type.toString()).to.equal('foo'); 70 | expect(parser.handle).to.be.a('function'); 71 | expect(parser.handle).to.have.length(1); 72 | }); 73 | 74 | it('should not have any response handlers', function() { 75 | expect(server._resHandlers).to.have.length(0); 76 | }); 77 | }); 78 | 79 | describe('registering a grant parsing function by type and phase', function() { 80 | const server = new Server(); 81 | const mod = {}; 82 | server.grant('foo', 'request', function(req) {}); 83 | 84 | it('should have one request parser', function() { 85 | expect(server._reqParsers).to.have.length(1); 86 | const parser = server._reqParsers[0]; 87 | expect(parser.type.toString()).to.equal('foo'); 88 | expect(parser.handle).to.be.a('function'); 89 | expect(parser.handle).to.have.length(1); 90 | }); 91 | 92 | it('should not have any response handlers', function() { 93 | expect(server._resHandlers).to.have.length(0); 94 | }); 95 | }); 96 | 97 | describe('registering a wildcard grant parsing function', function() { 98 | const server = new Server(); 99 | const mod = {}; 100 | server.grant('*', function(req) {}); 101 | 102 | it('should have one request parser', function() { 103 | expect(server._reqParsers).to.have.length(1); 104 | const parser = server._reqParsers[0]; 105 | expect(parser.type).to.be.null; 106 | expect(parser.handle).to.be.a('function'); 107 | expect(parser.handle).to.have.length(1); 108 | }); 109 | 110 | it('should not have any response handlers', function() { 111 | expect(server._resHandlers).to.have.length(0); 112 | }); 113 | }); 114 | 115 | describe('registering a grant responding function by type and phase', function() { 116 | const server = new Server(); 117 | const mod = {}; 118 | server.grant('foo', 'response', function(txn, res, next) {}); 119 | 120 | it('should not have any request parsers', function() { 121 | expect(server._reqParsers).to.have.length(0); 122 | }); 123 | 124 | it('should have one response handler', function() { 125 | expect(server._resHandlers).to.have.length(1); 126 | const handler = server._resHandlers[0]; 127 | expect(handler.type.toString()).to.equal('foo'); 128 | expect(handler.handle).to.be.a('function'); 129 | expect(handler.handle).to.have.length(3); 130 | }); 131 | }); 132 | 133 | describe('registering a wildcard grant responding function', function() { 134 | const server = new Server(); 135 | const mod = {}; 136 | server.grant('*', 'response', function(txn, res, next) {}); 137 | 138 | it('should not have any request parsers', function() { 139 | expect(server._reqParsers).to.have.length(0); 140 | }); 141 | 142 | it('should have one response handler', function() { 143 | expect(server._resHandlers).to.have.length(1); 144 | const handler = server._resHandlers[0]; 145 | expect(handler.type).to.be.null; 146 | expect(handler.handle).to.be.a('function'); 147 | expect(handler.handle).to.have.length(3); 148 | }); 149 | }); 150 | }); 151 | -------------------------------------------------------------------------------- /test/server.test.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2013,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | const Server = require('../lib/server'); 8 | const expect = require('chai').expect; 9 | 10 | describe('Server', function() { 11 | describe('newly initialized instance', function() { 12 | const server = new Server(); 13 | 14 | it('should wrap authorization middleware', function() { 15 | expect(server.authorization).to.be.a('function'); 16 | expect(server.authorization).to.have.length(3); 17 | expect(server.authorize).to.equal(server.authorization); 18 | }); 19 | 20 | it('should wrap decision middleware', function() { 21 | expect(server.decision).to.be.a('function'); 22 | expect(server.decision).to.have.length(2); 23 | }); 24 | 25 | it('should wrap token middleware', function() { 26 | expect(server.token).to.be.a('function'); 27 | expect(server.token).to.have.length(1); 28 | }); 29 | 30 | it('should wrap errorHandler middleware', function() { 31 | expect(server.errorHandler).to.be.a('function'); 32 | expect(server.errorHandler).to.have.length(1); 33 | }); 34 | 35 | it('should have no request parsers', function() { 36 | expect(server._reqParsers).to.have.length(0); 37 | }); 38 | 39 | it('should have no response handlers', function() { 40 | expect(server._resHandlers).to.have.length(0); 41 | }); 42 | 43 | it('should have no exchanges', function() { 44 | expect(server._exchanges).to.have.length(0); 45 | }); 46 | 47 | it('should have no serializers or deserializers', function() { 48 | expect(server._serializers).to.have.length(0); 49 | expect(server._deserializers).to.have.length(0); 50 | }); 51 | }); 52 | 53 | describe('#authorization', function() { 54 | const server = new Server(); 55 | 56 | it('should create function handler', function() { 57 | const handler = server.authorization(function() {}); 58 | expect(handler).to.be.an('function'); 59 | expect(handler).to.have.length(3); 60 | }); 61 | }); 62 | 63 | describe('#decision', function() { 64 | const server = new Server(); 65 | 66 | it('should create handler stack with two functions', function() { 67 | const handler = server.decision(); 68 | expect(handler).to.be.an('array'); 69 | expect(handler).to.have.length(2); 70 | expect(handler[0]).to.be.a('function'); 71 | expect(handler[0]).to.have.length(3); 72 | expect(handler[1]).to.be.a('function'); 73 | expect(handler[1]).to.have.length(3); 74 | }); 75 | 76 | it('should create function handler when transaction loader is disabled', function() { 77 | const handler = server.decision({loadTransaction: false}); 78 | expect(handler).to.be.an('function'); 79 | expect(handler).to.have.length(3); 80 | }); 81 | }); 82 | 83 | describe('#token', function() { 84 | const server = new Server(); 85 | 86 | it('should create function handler', function() { 87 | const handler = server.token(); 88 | expect(handler).to.be.an('function'); 89 | expect(handler).to.have.length(3); 90 | }); 91 | }); 92 | 93 | describe('#errorHandler', function() { 94 | const server = new Server(); 95 | 96 | it('should create function error handler', function() { 97 | const handler = server.errorHandler(); 98 | expect(handler).to.be.an('function'); 99 | expect(handler).to.have.length(4); 100 | }); 101 | }); 102 | }); 103 | -------------------------------------------------------------------------------- /test/unorderedlist.test.js: -------------------------------------------------------------------------------- 1 | // Copyright IBM Corp. 2013,2017. All Rights Reserved. 2 | // Node module: loopback-component-oauth2 3 | // This file is licensed under the MIT License. 4 | // License text available at https://opensource.org/licenses/MIT 5 | 6 | 'use strict'; 7 | const UnorderedList = require('../lib/unorderedlist'); 8 | const expect = require('chai').expect; 9 | 10 | describe('UnorderedList', function() { 11 | describe('constructed with a single element array', function() { 12 | const ul = new UnorderedList(['a']); 13 | 14 | it('should have correct length', function() { 15 | expect(ul).to.have.length(1); 16 | expect(ul._items[0]).to.equal('a'); 17 | }); 18 | 19 | it('should convert to string', function() { 20 | expect(ul.toString()).to.equal('a'); 21 | }); 22 | 23 | it('should be equal to list with same item', function() { 24 | const other = new UnorderedList(['a']); 25 | expect(ul.equalTo(other)).to.be.true; 26 | }); 27 | 28 | it('should be equal to array with same item', function() { 29 | expect(ul.equalTo(['a'])).to.be.true; 30 | }); 31 | 32 | it('should not be equal to list with superset of item', function() { 33 | const other = new UnorderedList(['a', 'b']); 34 | expect(ul.equalTo(other)).to.be.false; 35 | }); 36 | 37 | it('should check if it contains element', function() { 38 | expect(ul.contains('a')).to.be.true; 39 | expect(ul.contains('b')).to.be.false; 40 | }); 41 | 42 | it('should check if it contains any element', function() { 43 | expect(ul.containsAny(['a'])).to.be.true; 44 | expect(ul.containsAny(['b'])).to.be.false; 45 | expect(ul.containsAny(['1', 'a'])).to.be.true; 46 | expect(ul.containsAny(['2', 'b'])).to.be.false; 47 | }); 48 | }); 49 | 50 | describe('constructed with a multiple element array', function() { 51 | const ul = new UnorderedList(['a', 'b']); 52 | 53 | it('should have correct length', function() { 54 | expect(ul).to.have.length(2); 55 | expect(ul._items[0]).to.equal('a'); 56 | expect(ul._items[1]).to.equal('b'); 57 | }); 58 | 59 | it('should convert to string', function() { 60 | expect(ul.toString()).to.equal('a b'); 61 | }); 62 | 63 | it('should be equal to list with same set of items', function() { 64 | const other = new UnorderedList(['a', 'b']); 65 | expect(ul.equalTo(other)).to.be.true; 66 | }); 67 | 68 | it('should be equal to list with same set of items in different order', function() { 69 | const other = new UnorderedList(['b', 'a']); 70 | expect(ul.equalTo(other)).to.be.true; 71 | }); 72 | 73 | it('should not be equal to list with subset of items', function() { 74 | const other = new UnorderedList(['a']); 75 | expect(ul.equalTo(other)).to.be.false; 76 | }); 77 | 78 | it('should not be equal to list with superset of items', function() { 79 | const other = new UnorderedList(['a', 'b', 'c']); 80 | expect(ul.equalTo(other)).to.be.false; 81 | }); 82 | 83 | it('should check if it contains element', function() { 84 | expect(ul.contains('a')).to.be.true; 85 | expect(ul.contains('b')).to.be.true; 86 | expect(ul.contains('c')).to.be.false; 87 | }); 88 | 89 | it('should check if it contains any element', function() { 90 | expect(ul.containsAny(['a'])).to.be.true; 91 | expect(ul.containsAny(['b'])).to.be.true; 92 | expect(ul.containsAny(['c'])).to.be.false; 93 | expect(ul.containsAny(['1', 'a'])).to.be.true; 94 | expect(ul.containsAny(['2', 'b'])).to.be.true; 95 | expect(ul.containsAny(['3', 'c'])).to.be.false; 96 | }); 97 | }); 98 | 99 | describe('constructed with string', function() { 100 | const ul = new UnorderedList('foobar'); 101 | 102 | it('should have correct length', function() { 103 | expect(ul).to.have.length(1); 104 | expect(ul._items[0]).to.equal('foobar'); 105 | }); 106 | 107 | it('should convert to string', function() { 108 | expect(ul.toString()).to.equal('foobar'); 109 | }); 110 | }); 111 | 112 | describe('constructed with space separated string', function() { 113 | const ul = new UnorderedList('foo bar'); 114 | 115 | it('should have correct length', function() { 116 | expect(ul).to.have.length(2); 117 | expect(ul._items[0]).to.equal('foo'); 118 | expect(ul._items[1]).to.equal('bar'); 119 | }); 120 | 121 | it('should convert to string', function() { 122 | expect(ul.toString()).to.equal('foo bar'); 123 | }); 124 | }); 125 | }); 126 | --------------------------------------------------------------------------------