├── Guides ├── AdobeStock.md ├── GuidesOverview.md ├── AdobeCampaign.md ├── AdobeLaunch.md ├── AdobeTarget.md ├── CreativeSDK.md ├── AdobeAnalytics.md ├── AdobePhotoshop.md └── AdobeExperiencePlatform.md ├── JWT ├── samples │ ├── adobe-jwt-java │ │ ├── secret.key │ │ ├── readme.md │ │ ├── src │ │ │ └── main │ │ │ │ ├── resources │ │ │ │ └── config.properties │ │ │ │ └── java │ │ │ │ └── io │ │ │ │ └── adobe │ │ │ │ └── solutions │ │ │ │ └── IMSClient.java │ │ └── pom.xml │ ├── adobe-jwt-node │ │ ├── app.js │ │ ├── package.json │ │ ├── readme.md │ │ └── config.js │ ├── adobe-jwt-python │ │ ├── readme.md │ │ └── jwtencode.py │ ├── adobe-jwt-dotnet │ │ ├── readme.md │ │ └── Program.cs │ ├── adobe-jwt-php │ │ ├── readme.md │ │ └── AccessTokenProvider.php │ └── samples.md ├── JWTCertificate.md ├── Scopes.md └── JWT.md ├── OAuth ├── samples │ ├── adobe-auth-python │ │ ├── .gitignore │ │ ├── config.py │ │ ├── templates │ │ │ └── index.html │ │ ├── adobe-oauth2.0.py │ │ └── readme.md │ ├── .DS_Store │ ├── adobe-auth-node │ │ ├── .gitignore │ │ ├── public │ │ │ └── stylesheets │ │ │ │ └── style.css │ │ ├── views │ │ │ └── index.pug │ │ ├── package.json │ │ ├── server │ │ │ └── index.js │ │ └── readme.md │ └── samples.md ├── Scopes.md └── OAuth.md ├── Images ├── OP_1.png ├── OP_2.png ├── OP_3.png ├── OP_4.png ├── OP_5.png ├── PM_1.png ├── PM_2.png ├── PM_3.png ├── PM_4.png ├── PM_5.png ├── PM_6.png ├── PMW_1.png ├── PMW_2.png ├── PMW_3.png ├── PM_JWT_1.png ├── PM_JWT_2.png ├── PM_JWT_3.png ├── PM_JWT_4.png ├── PM_JWT_5.png ├── api-key-1.png ├── api-key-2.png ├── api-key-3.png ├── api-key-4.png ├── api-key-5.png ├── api-key-6.png ├── api-key-7.png ├── oauth-0.png ├── oauth-1.png ├── oauth-2.png ├── oauth-3.png ├── oauth-4.png ├── oauth-5.png ├── oauth-6.png ├── access_grant.png ├── auth_jwtqs_00.png ├── auth_jwtqs_000.png ├── auth_jwtqs_01.png ├── auth_jwtqs_02.png ├── auth_jwtqs_03.png ├── auth_jwtqs_04.png ├── auth_jwtqs_05.png ├── auth_jwtqs_06.png ├── auth_jwtqs_07.png ├── auth_jwtqs_08.png ├── login_screen.png └── credentials_page.png ├── COPYRIGHT ├── Resources ├── Tools │ ├── ToolsOverview.md │ ├── OAuthPlayground.md │ └── Postman.md └── IMS.md ├── Support └── Index.md ├── LICENSE ├── FAQ └── Index.md ├── README.md ├── AuthenticationOverview ├── AuthenticationGuide.md ├── OAuthIntegration.md ├── APIKeyIntegration.md └── ServiceAccountIntegration.md ├── Backup ├── OAuth2.0Endpoints │ ├── oauth-scopes.md │ └── web-oauth2.0-guide.md ├── idTypes.md ├── JWTAuthenticationQuickStart.md └── postmanQuickStart.md ├── CODE_OF_CONDUCT.md └── manifest.json /Guides/AdobeStock.md: -------------------------------------------------------------------------------- 1 | # Adobe Stock 2 | 3 | ## Coming Soon 4 | -------------------------------------------------------------------------------- /Guides/GuidesOverview.md: -------------------------------------------------------------------------------- 1 | # Guides 2 | 3 | ## Coming Soon 4 | -------------------------------------------------------------------------------- /Guides/AdobeCampaign.md: -------------------------------------------------------------------------------- 1 | # Adobe Campaign 2 | 3 | ## Coming Soon 4 | -------------------------------------------------------------------------------- /Guides/AdobeLaunch.md: -------------------------------------------------------------------------------- 1 | # Adobe Launch 2 | 3 | ## Coming Soon 4 | -------------------------------------------------------------------------------- /Guides/AdobeTarget.md: -------------------------------------------------------------------------------- 1 | # Adobe Target 2 | 3 | ## Coming Soon 4 | -------------------------------------------------------------------------------- /Guides/CreativeSDK.md: -------------------------------------------------------------------------------- 1 | # Creative SDK 2 | 3 | ## Coming Soon 4 | -------------------------------------------------------------------------------- /JWT/samples/adobe-jwt-java/secret.key: -------------------------------------------------------------------------------- 1 | < TO BE CREATED BY USER > 2 | -------------------------------------------------------------------------------- /Guides/AdobeAnalytics.md: -------------------------------------------------------------------------------- 1 | # Adobe Analytics 2 | 3 | ## Coming soon 4 | -------------------------------------------------------------------------------- /Guides/AdobePhotoshop.md: -------------------------------------------------------------------------------- 1 | # Adobe Photoshop 2 | 3 | ## Coming Soon 4 | -------------------------------------------------------------------------------- /OAuth/samples/adobe-auth-python/.gitignore: -------------------------------------------------------------------------------- 1 | cert.pem 2 | key.pem 3 | *.pyc 4 | -------------------------------------------------------------------------------- /Images/OP_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/OP_1.png -------------------------------------------------------------------------------- /Images/OP_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/OP_2.png -------------------------------------------------------------------------------- /Images/OP_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/OP_3.png -------------------------------------------------------------------------------- /Images/OP_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/OP_4.png -------------------------------------------------------------------------------- /Images/OP_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/OP_5.png -------------------------------------------------------------------------------- /Images/PM_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/PM_1.png -------------------------------------------------------------------------------- /Images/PM_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/PM_2.png -------------------------------------------------------------------------------- /Images/PM_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/PM_3.png -------------------------------------------------------------------------------- /Images/PM_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/PM_4.png -------------------------------------------------------------------------------- /Images/PM_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/PM_5.png -------------------------------------------------------------------------------- /Images/PM_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/PM_6.png -------------------------------------------------------------------------------- /Guides/AdobeExperiencePlatform.md: -------------------------------------------------------------------------------- 1 | # Adobe Experience Platform 2 | 3 | ## Coming Soon 4 | -------------------------------------------------------------------------------- /Images/PMW_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/PMW_1.png -------------------------------------------------------------------------------- /Images/PMW_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/PMW_2.png -------------------------------------------------------------------------------- /Images/PMW_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/PMW_3.png -------------------------------------------------------------------------------- /Images/PM_JWT_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/PM_JWT_1.png -------------------------------------------------------------------------------- /Images/PM_JWT_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/PM_JWT_2.png -------------------------------------------------------------------------------- /Images/PM_JWT_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/PM_JWT_3.png -------------------------------------------------------------------------------- /Images/PM_JWT_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/PM_JWT_4.png -------------------------------------------------------------------------------- /Images/PM_JWT_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/PM_JWT_5.png -------------------------------------------------------------------------------- /Images/api-key-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/api-key-1.png -------------------------------------------------------------------------------- /Images/api-key-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/api-key-2.png -------------------------------------------------------------------------------- /Images/api-key-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/api-key-3.png -------------------------------------------------------------------------------- /Images/api-key-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/api-key-4.png -------------------------------------------------------------------------------- /Images/api-key-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/api-key-5.png -------------------------------------------------------------------------------- /Images/api-key-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/api-key-6.png -------------------------------------------------------------------------------- /Images/api-key-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/api-key-7.png -------------------------------------------------------------------------------- /Images/oauth-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/oauth-0.png -------------------------------------------------------------------------------- /Images/oauth-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/oauth-1.png -------------------------------------------------------------------------------- /Images/oauth-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/oauth-2.png -------------------------------------------------------------------------------- /Images/oauth-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/oauth-3.png -------------------------------------------------------------------------------- /Images/oauth-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/oauth-4.png -------------------------------------------------------------------------------- /Images/oauth-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/oauth-5.png -------------------------------------------------------------------------------- /Images/oauth-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/oauth-6.png -------------------------------------------------------------------------------- /Images/access_grant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/access_grant.png -------------------------------------------------------------------------------- /Images/auth_jwtqs_00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/auth_jwtqs_00.png -------------------------------------------------------------------------------- /Images/auth_jwtqs_000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/auth_jwtqs_000.png -------------------------------------------------------------------------------- /Images/auth_jwtqs_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/auth_jwtqs_01.png -------------------------------------------------------------------------------- /Images/auth_jwtqs_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/auth_jwtqs_02.png -------------------------------------------------------------------------------- /Images/auth_jwtqs_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/auth_jwtqs_03.png -------------------------------------------------------------------------------- /Images/auth_jwtqs_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/auth_jwtqs_04.png -------------------------------------------------------------------------------- /Images/auth_jwtqs_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/auth_jwtqs_05.png -------------------------------------------------------------------------------- /Images/auth_jwtqs_06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/auth_jwtqs_06.png -------------------------------------------------------------------------------- /Images/auth_jwtqs_07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/auth_jwtqs_07.png -------------------------------------------------------------------------------- /Images/auth_jwtqs_08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/auth_jwtqs_08.png -------------------------------------------------------------------------------- /Images/login_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/login_screen.png -------------------------------------------------------------------------------- /OAuth/samples/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/OAuth/samples/.DS_Store -------------------------------------------------------------------------------- /Images/credentials_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdobeDocs/adobeio-auth/HEAD/Images/credentials_page.png -------------------------------------------------------------------------------- /OAuth/samples/adobe-auth-node/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | node_modules 3 | server/localhost-key.pem 4 | server/localhost.pem -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | © Copyright 2015-2018 Adobe. All rights reserved. 2 | 3 | Adobe holds the copyright for all the files found in this repository. 4 | 5 | See the LICENSE file for licensing information. 6 | -------------------------------------------------------------------------------- /JWT/samples/adobe-jwt-node/app.js: -------------------------------------------------------------------------------- 1 | const auth=require("@adobe/jwt-auth"); 2 | const _config=require("./config.js"); 3 | let options=_config.credentials; 4 | auth(options).then(res => console.log(res)); 5 | 6 | -------------------------------------------------------------------------------- /JWT/samples/adobe-jwt-python/readme.md: -------------------------------------------------------------------------------- 1 | This is a simple example of how to get an access token in python 2 | 3 | You will need to install the necessary dependencies 4 | ```pip install PyJWT``` 5 | 6 | You will also need to replace all of the variables encapsulated in {} with your own values 7 | -------------------------------------------------------------------------------- /OAuth/samples/adobe-auth-python/config.py: -------------------------------------------------------------------------------- 1 | class Config(object): 2 | # Replace below secret key with your secret 3 | # Reference: http://flask.pocoo.org/docs/0.12/quickstart/#sessions. 4 | FLASK_SECRET = 'PLACEHOLDER_SECRET_KEY' 5 | ADOBE_API_KEY = 'YOUR_ADOBE_KEY' 6 | ADOBE_API_SECRET = 'YOUR_ADOBE_SECRET' -------------------------------------------------------------------------------- /JWT/samples/adobe-jwt-node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "adobe-jwt-node", 3 | "version": "1.0.0", 4 | "description": "This is a sample code", 5 | "scripts": { 6 | "start": "node app.js" 7 | }, 8 | "author": "Hiren Shah", 9 | "license": "MIT", 10 | "dependencies": { 11 | "@adobe/jwt-auth": "^0.3.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /JWT/samples/adobe-jwt-node/readme.md: -------------------------------------------------------------------------------- 1 | # Steps 2 | 1. Download and extract the repo 3 | 4 | 2. Edit the config files and add API Key, Client Secret, Org ID, Technical Account ID and Private key from your Adobe Developer Console integration. 5 | 6 | 3. Execute below commands 7 | 8 | ```npm install``` 9 | 10 | 11 | ```node app.js``` 12 | -------------------------------------------------------------------------------- /Resources/Tools/ToolsOverview.md: -------------------------------------------------------------------------------- 1 | 2 | # Tools Overview 3 | 4 | 5 | ## [OAuth 2.0 Playground](OAuthPlayground.md) 6 | Do you have an OAuth integration created? Try the OAuth 2.0 Playground tool to generate an access token. 7 | 8 | ## [Postman](Postman.md) 9 | Try Postman for generating an access token for both OAuth and Service Account Integration. 10 | -------------------------------------------------------------------------------- /OAuth/samples/adobe-auth-node/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: sans-serif; 3 | } 4 | 5 | button { 6 | display: block; 7 | margin: 10px auto; 8 | } 9 | 10 | body { 11 | margin: 60px 40px; 12 | text-align: center; 13 | } 14 | 15 | .btn-group { 16 | margin: 20px auto; 17 | width: 30%; 18 | } 19 | 20 | .title { 21 | display: inline-block; 22 | padding-bottom: -10px; 23 | text-align: center; 24 | margin: 20px; 25 | } 26 | -------------------------------------------------------------------------------- /OAuth/samples/adobe-auth-node/views/index.pug: -------------------------------------------------------------------------------- 1 | doctype 2 | html 3 | head 4 | title Adobe Auth Example 5 | link(rel='stylesheet', href='/stylesheets/style.css') 6 | body 7 | header 8 | h1 Adobe Auth App 9 | .button-group 10 | button(onclick="location.href='/login'") Log In with Adobe 11 | button(onclick="location.href='/profile'") Get Profile 12 | button(onclick="location.href='/logout'") Log Out 13 | .canvas 14 | p= response -------------------------------------------------------------------------------- /OAuth/samples/adobe-auth-node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "adobe-auth-node", 3 | "version": "1.0.0", 4 | "description": "adobe auth node example", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node ./server/index.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "axios": "^0.21.4", 14 | "dotenv": "^10.0.0", 15 | "express": "^4.16.3", 16 | "express-session": "^1.15.6", 17 | "pug": "^3.0.2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Support/Index.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | Learn where to ask questions, report bugs, make feature requests, and spark discussions. 4 | 5 | ## [FAQ](../FAQ/Index.md) 6 | 7 | A knowledge base of frequently asked questions. This is a great starting place to find an answer before asking your question. 8 | 9 | ## [GitHub Issues](https://github.com/AdobeDocs/adobeio-auth/issues) 10 | 11 | This is the place to report bugs, ask questions, make feature requests, or start a discussion. You'll find official Adobe developers and community members available to help you out. 12 | -------------------------------------------------------------------------------- /OAuth/samples/samples.md: -------------------------------------------------------------------------------- 1 | # Sample Code 2 | 3 | The following samples demonstrate basic interaction with the Adobe OAuth endpoints. 4 | 5 | - **Node.js Example** 6 | [Github repo](https://github.com/AdobeDocs/adobeio-auth/tree/stage/OAuth/samples/adobe-auth-node) where you can find a complete Node.js-based web app example that uses Adobe OAuth. 7 | 8 | - **Python Example** 9 | [Github repo](https://github.com/AdobeDocs/adobeio-auth/tree/stage/OAuth/samples/adobe-auth-python) where you can find a complete Python based web app example that uses Adobe OAuth. 10 | -------------------------------------------------------------------------------- /OAuth/samples/adobe-auth-python/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Adobe Auth Example 6 | 7 | 8 |
9 |

Adobe Auth App

10 |
11 |
12 | 13 | 14 |
15 |
16 | {{ response }} 17 |
18 | 19 | -------------------------------------------------------------------------------- /JWT/samples/adobe-jwt-java/readme.md: -------------------------------------------------------------------------------- 1 | # Steps 2 | 3 | 1. create the certificate and private key using openssl 4 | 5 | ```$ openssl req -nodes -text -x509 -newkey rsa:2048 -keyout secret.pem -out certificate.pem -days 356``` 6 | 7 | 2. Upload the certificate.pem in Adobe IO Console-> Your Integration-> Public keys 8 | 9 | 3. convert private key to DER format 10 | 11 | ```$ openssl pkcs8 -topk8 -inform PEM -outform DER -in secret.pem -nocrypt > secret.key``` 12 | 13 | 4. Edit the config.properties in src/main/resources/ and add the values from your Adobe Developer Console integration. 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /JWT/samples/adobe-jwt-dotnet/readme.md: -------------------------------------------------------------------------------- 1 | 2 | # Steps 3 | 4 | 1. create the certificate and private key using openssl 5 | 6 | ```$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout private.key -out certificate_pub.crt``` 7 | 8 | 2. Upload the certificate_pub.crt in Adobe IO Console-> Your Integration-> Public keys 9 | 10 | 3. convert private key and certificate to pfx format 11 | 12 | ```$ openssl pkcs12 -export -out mycert.pfx -inkey private.key -in certificate_pub.crt``` 13 | 14 | 4. Edit the program.cs file and add the properties from your Adobe Developer Console integration. 15 | 16 | 17 | -------------------------------------------------------------------------------- /JWT/samples/adobe-jwt-java/src/main/resources/config.properties: -------------------------------------------------------------------------------- 1 | #Go to https://www.adobe.com/go/devs_console_ui -> Select your integration and copy the client credential from "Overview" 2 | #API Key (Client ID) 3 | apiKey=6cdd92XXXXXXXXb82de19827..... 4 | 5 | #Technical account ID 6 | technicalAccountId=95FXXXXXXXXBA542B9....@techacct.adobe.com 7 | 8 | #Organization ID 9 | orgId=C74FXXXXXX4880XXXXX9@AdobeOrg 10 | 11 | #Client secret 12 | secret=ae2XXXXc-XXXX-XXXX-bf77-b35..... 13 | 14 | #Go to "JWT" section of the integration and copy below values 15 | #exp 16 | expirationTime=600 17 | 18 | #scopes e.g. ent_user_sdk from "https://ims-na1.adobelogin.com/s/ent_user_sdk" 19 | metascopes=ent_user_sdk 20 | 21 | #Path to secret.key file for the certificate uploaded in console.adobe.io integration 22 | key_path=secret.key 23 | 24 | #URL Endpoints 25 | imsHost=ims-na1.adobelogin.com 26 | imsExchange=https://ims-na1.adobelogin.com/ims/exchange/jwt 27 | 28 | -------------------------------------------------------------------------------- /JWT/samples/adobe-jwt-java/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | 1.7 9 | 1.7 10 | 11 | 12 | io.adobe.solutions 13 | IMS-Client 14 | 1.0-SNAPSHOT 15 | 16 | 17 | 18 | 19 | io.jsonwebtoken 20 | jjwt 21 | 0.9.0 22 | 23 | 24 | 25 | org.json 26 | json 27 | 20171018 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /JWT/samples/adobe-jwt-php/readme.md: -------------------------------------------------------------------------------- 1 | # PHP JWT Provider and auth example 2 | 3 | This is a PHP implementation to prepare JWT and shows an example login to AdobeIO to obtain `access_token`, it does not use any external library and calls `openssl_sign` and other functions available in PHP to build JWT. 4 | 5 | The method `doAdobeIOAuth($jwt,$client_id,$client_secret)` should be used as reference for login, it uses prepared JWT to do an authentication on AdobeIO and fetch `access_token`. 6 | 7 | **To Run** 8 | 1. Download and extract the repo 9 | 10 | 2. Run PHP AccessTokenProvider.php to auth and get AdobeIO Access Token 11 | 12 | 3. Execute below commands 13 | 14 | **Usage** 15 | 16 | ```AccessTokenProvider.php -i -s -k -u -b -c -e ``` 17 | 18 | **Example** 19 | 20 | ```php JWT/samples/adobe-jwt-php/AccessTokenProvider.php -i"e1b8b4c4109c48....." -s"965f8635-........" -k"/Path/of/private.key" -u"DD0E3......@AdobeOrg" -b"D36......@techacct.adobe.com" -c"ent_reactor_sdk,ent_adobeio_sdk" -e"1 day"``` 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | © Copyright 2018 Adobe. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /FAQ/Index.md: -------------------------------------------------------------------------------- 1 | # Frequently Asked Questions 2 | 3 | - [Where can I find the sample code for OAuth authentication?](#where-can-i-find-the-sample-code-for-oauth-authentication) 4 | - [How to use the private key for generating a JWT?](#how-to-use-the-private-key-for-generating-a-jwt) 5 | - [What does Default Redirect URI and the Redirect URI Pattern means?](#what-does-default-redirect-uri-and-the-redirect-uri-pattern-means) 6 | 7 | ### Where can I find the sample code for OAuth authentication? 8 | There are currently code samples available for [NodeJS](https://github.com/AdobeDocs/adobeio-auth/tree/master/OAuth/samples/adobe-auth-node) and [Python](https://github.com/AdobeDocs/adobeio-auth/tree/master/OAuth/samples/adobe-auth-python). 9 | 10 | ### How to use the private key for generating a JWT? 11 | Please copy the full content of private key including `-----BEGIN PRIVATE KEY-----` and `-----END PRIVATE KEY-----` to generate a correct JWT token. 12 | 13 | ### What do Default Redirect URI and the Redirect URI Pattern mean? 14 | The default redirect URI is the URL where Adobe Identity Management Service (IMS) will send the authorization code after a successful login with Adobe. You will need that code to make a call to the token endpoint to receive an access token. 15 | 16 | The redirect URI pattern is a regex representation of allowed URLs to receive the authorization code. It is used when you pass an optional parameter `redirect_url` with your request. 17 | -------------------------------------------------------------------------------- /JWT/samples/samples.md: -------------------------------------------------------------------------------- 1 | ## Sample Code 2 | 3 | The following samples demonstrate JWT generation and exchanging it with Adobe IMS endpoint to retrieve an access token. 4 | 5 | ### Node.js Example 6 | [Github repo](https://github.com/AdobeDocs/adobeio-auth/tree/stage/JWT/samples/adobe-jwt-node) where you can find a complete sample Node.js code to generate a JWT and exchanging it with Adobe IMS Endpoint to retrieve an access token. 7 | 8 | ### Java Example 9 | [Github repo](https://github.com/AdobeDocs/adobeio-auth/tree/stage/JWT/samples/adobe-jwt-java) where you can find a complete sample Java code to generate a JWT and exchanging it with Adobe IMS Endpoint to retrieve an access token. 10 | 11 | ### Python Example 12 | [Github repo](https://github.com/AdobeDocs/adobeio-auth/tree/stage/JWT/samples/adobe-jwt-python) where you can find a complete sample Python code to generate a JWT and exchanging it with Adobe IMS Endpoint to retrieve an access token. 13 | 14 | ### C#.NET Example 15 | [Github repo](https://github.com/AdobeDocs/adobeio-auth/tree/stage/JWT/samples/adobe-jwt-dotnet) where you can find a complete sample C#.NET code to generate a JWT and exchanging it with Adobe IMS Endpoint to retrieve an access token. 16 | 17 | ### PHP Example 18 | [Github repo](https://github.com/AdobeDocs/adobeio-auth/tree/stage/JWT/samples/adobe-jwt-php) where you can find PHP code example for JWT creation and reference method that exchanges JWT with Adobe IMS Endpoint to retrieve an access token. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Developer Guide to Adobe I/O Authentication 2 | This guide contains all you need to know to authenticate your apps with Adobe services. 3 | 4 | In this Guide: 5 | - [Authentication Overview](AuthenticationOverview/AuthenticationGuide.md): Discover Adobe authentication models and find out about how to authenticate with Adobe in one of three ways, depending on your application model: 6 | - [API Key Integration](AuthenticationOverview/APIKeyIntegration.md) 7 | - [OAuth Integration](AuthenticationOverview/OAuthIntegration.md) 8 | - [Service Account Integration](AuthenticationOverview/ServiceAccountIntegration.md) 9 | - [OAuth Authentication](OAuth/OAuth.md): Get technical specifications on OAuth 2.0 authorization and authentication. Discover sample applications that can help you create your first integrations. 10 | - [JWT Authentication](JWT/JWT.md): Get technical specifications on JSON Web Token (JWT) authentication, the model used for service account integrations. Discover sample apps. 11 | - [Tools](Resources/Tools/ToolsOverview.md): Adobe recommends two tools for generating access tokens: 12 | - [OAuth 2.0 Playground](Resources/Tools/OAuthPlayground.md): This Adobe service generates OAuth access tokens. 13 | - [Postman](Resources/Tools/Postman.md): This third-party tool generates both OAuth and JWT tokens. 14 | - [IMS APIs](Resources/IMS.md): This guide shows you all the APIs for Adobe Identity Management Services (IMS). 15 | - [Support](Support/Index.md): Resources for getting your Adobe authentication questions answered. 16 | - [FAQ](FAQ.md): Answers to frequently asked questions. 17 | -------------------------------------------------------------------------------- /JWT/JWTCertificate.md: -------------------------------------------------------------------------------- 1 | # Create a Public Key Certificate 2 | 3 | Create a private key and a public certificate. Make sure you store these securely. 4 | 5 | ## MacOS and Linux: 6 | 7 | Open a terminal and execute the following command: 8 | 9 | `openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout private.key -out certificate_pub.crt` 10 | 11 | ![Generate public certificate](../Images/auth_jwtqs_00.png "Generate Public certificate") 12 | 13 | ## Windows: 14 | 15 | 1. Download an OpenSSL client to generate public certificates; for example, you can try the [OpenSSL Windows client](https://bintray.com/vszakats/generic/download_file?file_path=openssl-1.1.1-win64-mingw.zip). 16 | 17 | 2. Extract the folder and copy it to the **C:/libs/** location. 18 | 19 | 3. Open a command-line window and execute the following commands: 20 | 21 | ``` 22 | set OPENSSL_CONF=C:/libs/openssl-1.1.1-win64-mingw/openssl.cnf 23 | 24 | cd C:/libs/openssl-1.1.1-win64-mingw/ 25 | 26 | openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout private.key -out certificate_pub.crt 27 | ``` 28 | ![Generate public certificate windows](../Images/auth_jwtqs_000.png "Generate Public certificate windows") 29 | 30 | 4. Once you’ve completed the steps for your chosen platform, continue in the Adobe Developer Console. 31 | 32 | ## Using the Public Key Certificate for Service Account Integration 33 | 34 | 1. Upload the public certificate (certificate_pub.crt) as a part of creating the integration. 35 | 36 | ![Upload public certificate](../Images/auth_jwtqs_03.png "Upload public certificate") 37 | 38 | 2. Your integration should now be created with the appropriate public certificate and claims. 39 | 40 | ![Integration created](../Images/auth_jwtqs_04.png "Integration created") 41 | -------------------------------------------------------------------------------- /Resources/Tools/OAuthPlayground.md: -------------------------------------------------------------------------------- 1 | # OAuth 2.0 Playground 2 | 3 | The OAuth 2.0 Playground is an Adobe internet utility that enables developers to easily obtain an OAuth 2.0 access token for use in building and testing their integrations. Before you use the OAuth 2.0 Playground, you should already have created an integration you want to use for this purpose. The OAuth 2.0 Playground source code is also available for you to view and experiment with. 4 | 5 | ## Steps to obtain a token: 6 | 7 | 1. Go to [OAuth 2.0 Playground](https://adobeioruntime.net/api/v1/web/io-solutions/adobe-oauth-playground/oauth.html) 8 | 9 | ![op-1](../../Images/OP_1.png) 10 | 11 | 2. Go to the [Adobe Developer Console](https://www.adobe.com/go/devs_console_ui) 12 | 13 | 3. Create a project within Console. For complete steps to creating a project in Console, begin by reading the [Adobe Developer Console getting started guide]() and [projects overview](). 14 | 15 | 4. Once you have created a project, you will be able to add services including APIs, Adobe I/O Events registrations, and Adobe I/O Runtime. Add an API to your project and then select the services with which you wish to integrate (such as Adobe Analytics > OAuth 2.0 Integration) 16 | 17 | To add an API that uses OAuth authentication and authorization, follow the steps outlined in the guide for [adding an API to a project using OAuth authentication](). 18 | 19 | When the API has been successfully connected, you will be able to access the newly generated credentials including Client ID and Client Secret. 20 | 21 | 5. Copy your **Client ID** (API Key) and **Client Secret** from Adobe Developer Console into the OAuth 2.0 Playground. 22 | 23 | 6. Enter scopes as: 24 | `openid,read_organizations,additional_info.projectedProductContext,additional_info.job_function` 25 | 26 | ![op-3](../../Images/OP_3.png) 27 | 28 | 7. Click **Generate Tokens.** 29 | 30 | 8. You will be prompted for login by Adobe. Log in using your Adobe ID. 31 | 32 | ![op-4](../../Images/OP_4.png) 33 | 34 | 9. Your tokens will be generated. 35 | 36 | ![op-5](../../Images/OP_5.png) 37 | -------------------------------------------------------------------------------- /JWT/samples/adobe-jwt-python/jwtencode.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import json 3 | import jwt 4 | import os 5 | import requests 6 | 7 | # Config Data 8 | url = 'https://ims-na1.adobelogin.com/ims/exchange/jwt' 9 | jwtPayloadRaw = """{ "iss": "{The issuer, your Organization ID from the Adobe Developer Console integration, in the format org_ident@AdobeOrg}", 10 | "sub": "{The subject, your Technical Account ID from the Adobe Developer Console integration, in the format: id@techacct.adobe.com}", 11 | "{The API-access claim configured for your organization: https://ims-na1.adobelogin.com/s/ent_analytics_bulk_ingest_sdk}": true, 12 | "aud": "{The audience for the token, your API Key from the Adobe Developer Console integration, in the format: https://ims-na1.adobelogin.com/c/api_key}" }""" 13 | jwtPayloadJson = json.loads(jwtPayloadRaw) 14 | jwtPayloadJson["exp"] = datetime.datetime.utcnow() + datetime.timedelta(seconds=30) 15 | 16 | accessTokenRequestPayload = {'client_id': '{Your Client Id (API Key)}' 17 | ,'client_secret': 'Your Client Secret'} 18 | 19 | # Request Access Key 20 | #This Needs to point at where your private key is on the file system 21 | keyfile = open(os.path.join(os.path.expanduser('~'),'.ssh/private.key'),'r') 22 | private_key = keyfile.read() 23 | 24 | # Encode the jwt Token 25 | jwttoken = jwt.encode(jwtPayloadJson, private_key, algorithm='RS256') 26 | #print("Encoded JWT Token") 27 | #print(jwttoken.decode('utf-8')) 28 | 29 | 30 | # We are making a http request simmilar to this curl request 31 | #curl -X POST -H "Content-Type: multipart/form-data" -F "client_id=6e806c8aa87b42a49260d7a47a8d3218" -F "client_secret=f4813774-c72f-42ca-8039-3208ff189932" -F "jwt_token=`./jwtenc.sh`" https://ims-na1.adobelogin.com/ims/exchange/jwt 32 | accessTokenRequestPayload['jwt_token'] = jwttoken 33 | result = requests.post(url, data = accessTokenRequestPayload) 34 | resultjson = json.loads(result.text); 35 | #print("Full output from the access token request") 36 | #print(json.dumps(resultjson, indent=4, sort_keys=True)) 37 | 38 | # Echo out the access token 39 | print(resultjson["access_token"]); 40 | 41 | -------------------------------------------------------------------------------- /AuthenticationOverview/AuthenticationGuide.md: -------------------------------------------------------------------------------- 1 | # Adobe I/O Authentication Overview 2 | 3 | Adobe is committed to privacy and security. Nearly all Adobe services require your application to authenticate through the Adobe Identity Management System (IMS) to receive client credentials. The client credentials determine the access and permissions granted to your application. 4 | 5 | Any API that accesses a service, data or content on behalf of an end user authenticates using the OAuth or JSON Web Token standards. 6 | 7 | Use the [Adobe Developer Console](https://www.adobe.com/go/devs_console_ui/) to obtain client credentials by creating a new **Project**. Once you create a project, you can add APIs that include **API Keys** (Client ID) and other access credentials. You can then obtain a secure access token from Adobe for each API session. 8 | 9 | A project can include one or more services. In many cases, you will use the same client credentials to access multiple Adobe products and services. In addition to APIs, you may also add I/O Events and I/O Runtime to your projects so that your applications can access content and services in real-time. 10 | 11 | To learn more about creating projects in Adobe Developer Console, read the [Console getting started guide](https://www.adobe.com/go/devs_console_getting_started). 12 | 13 | ## Types of Authentication 14 | 15 | ### [API Key Integration (Authorization Only)](APIKeyIntegration.md) 16 | An API Key is the only client credential required for these services. These integrations do not need to pass an access token with each request. 17 | e.g. Adobe Stock 18 | 19 | ### [OAuth Integration (OAuth 2.0 authentication flow)](OAuthIntegration.md) 20 | If your integration needs to access content or a service on behalf of an end user, that user must be authenticated as well. Your integration will need to pass the OAuth token granted by the Adobe IMS. 21 | e.g. Creative SDK, Photoshop, Adobe Analytics 22 | 23 | ### [Service Account Integration (JWT authentication flow)](ServiceAccountIntegration.md) 24 | For service-to-service integrations, you will also need a JSON Web Token (JWT) that encapsulates your client credentials and authenticates the identity of your integration. You then exchange the JWT for the access token that authorizes access. 25 | e.g. Adobe Campaign, Adobe Launch, Adobe Target 26 | -------------------------------------------------------------------------------- /AuthenticationOverview/OAuthIntegration.md: -------------------------------------------------------------------------------- 1 | # OAuth Connection 2 | 3 | If your application needs to access Adobe services or content, you'll need a set of client credentials to authenticate your app and your user, and to authorize access. The type of application you are building will determine the type of client credentials you will need. 4 | 5 | To obtain client credentials for an app that accesses services on behalf of an **end-user**, you'll need to create an **OAuth** connection using the [Adobe Developer Console](https://www.adobe.io/console). You can integrate your app with more than one Adobe service. 6 | 7 | OAuth allows your end users to sign in to your integration with an Adobe ID. With an OAuth token, your application will be able to access Adobe services or content on behalf of the logged in user. 8 | 9 | If your application needs to access Adobe services or content on behalf of an organization (an Adobe enterprise organization), follow the steps for **[Service Account (JWT) Authentication](ServiceAccountIntegration.md)**. 10 | 11 | This article will walk you through the steps to set up an **OAuth** connection. 12 | 13 | ## OAuth connection workflow 14 | 15 | [Step 1: Create a project in Adobe Developer Console](#step-1-create-a-project-in-adobe-developer-console) 16 | 17 | [Step 2: Add an API to your project using OAuth authentication and authorization](#step-2-add-an-api-to-your-project-using-OAuth-authentication-and-authorization) 18 | 19 | [Step 3: Try It](#step-3-try-it) 20 | 21 | ### Step 1: Create a project in Adobe Developer Console 22 | 23 | Integrations are now created as part of a "project" within Adobe Developer Console. For complete steps to creating a project in Console, begin by reading the [Adobe Developer Console getting started guide](https://www.adobe.com/go/devs_console_getting_started) and [projects overview](https://www.adobe.com/go/devs_projects_overview). 24 | 25 | Once you have created a project, you will be able to add services including APIs, I/O Events, and I/O Runtime. 26 | 27 | ### Step 2: Add an API to your project using OAuth authentication and authorization 28 | 29 | To add an API that uses OAuth authentication and authorization, follow the steps outlined in the guide for [adding an API to a project using OAuth authentication](https://www.adobe.com/go/devs_projects_oauth). 30 | 31 | When the API has been successfully connected, you will be able to access the newly generated credentials including Client ID and Client Secret. 32 | 33 | ### Step 3: Try It 34 | 35 | Generate an access token using [OAuth 2.0 Playground](../Resources/Tools/OAuthPlayground.md) 36 | -------------------------------------------------------------------------------- /JWT/samples/adobe-jwt-node/config.js: -------------------------------------------------------------------------------- 1 | //console.adobe.io -> Integration -> Details 2 | 3 | module.exports = { 4 | credentials: { 5 | clientId : "bb11ebd6406a4f---------f705b26a", //Application ID (Client ID) 6 | technicalAccountId : "8EDD3561-------5CDB@techacct.adobe.com", //Technical account ID 7 | orgId : "EF2D363--------CA@AdobeOrg", // Org ID 8 | clientSecret : "c811f67e-9ed------------25ea148", //Client Secret 9 | metaScopes : "ent_user_sdk", // Metascopes 10 | privateKey : "-----BEGIN RSA PRIVATE KEY-----\n" + //Content of private.key 11 | "MIIEowIBAAKCAQEAtqX3bHwETnyOizuDUWoyT0PTreyQJ9Hkti+5CssnRULAsE/D\n" + 12 | "Yw6RyB8WLlC07mYxUkA/7Ikd1oEvTuAYLCSuJWXu0WBhXHrw6268xP60LjQl1Xu5\n" + 13 | "GQjrTiQll8c0N10dww6TzzupLyFOD/J+TsH9T2zZ/DYukP/x0iOGs/7D3IvJfRcq\n" + 14 | "6FOoAcKSV3geW7IRDnmn+dX4W3SWN/SS9OGRgYu16KBYV2+YvAkRtWM3nMdLuz6a\n" + 15 | "ep16MBZJQErYguowmhrSmLRFOzkZbXPjr6JZmZaNuuPLQnLYLA2p0RUzva5PThkw\n" + 16 | "esidMH2WZQ5dP+4aDA8mwz6eiI6z4+WR8gp3DwIDAQABAoIBADmMN1YGCTFVi3AR\n" + 17 | "E0IOrMVOwJ5XH+B8AIz------------------------------ZzVw45acX1JfMdk\n" + 18 | "UhlugTQlVsa/kE2cKtZzMKT8/3ZjVdxavCpIJiObvgCBclFTVHJF4Ip16MuBud/K\n" + 19 | "bsOP2akxycjupWNoUR/9s4544etV0smbm2wV/KUVth8VFdRMaE2b0xHeCOvS4MP2\n" + 20 | "j1sSqdSmKUBddooFjQwDC/poOQC0GYj+VXEiHrR/uk/P/ipO2Q7N4+2DIDXAe1d7\n" + 21 | "0A6reBaPagbvH---------------------------oX52CDVFJRQzncCXe6WD9tPT\n" + 22 | "ldx9F6ECgYEA8fMntK4pjLKVGkmjuHCmYZqCQfElbxZWBGgeTi6TtQAC/K0NqivL\n" + 23 | "57SMjiZEdE1Ct716PHs8YCHNVQVdPD2Bpv9HXq9Jcz+nQj0onofqsplnj/0nH3ls\n" + 24 | "fJGo27nB8LYDINWXEY3Mr8H7/Xs5/lQIDdoadWriJHCifO0sSdih/b8CgYEAwUE6\n" + 25 | "/PtHPp315mI33azUwZDZ+G4DwI2WICoGs9Z1RlqH8Zk3X11djpGurNNK5/JcPtSS\n" + 26 | "No4CAEX4VYue+N2jtQnJNzH+IhLFBGDwz1JMBMBw1ye8SVtvvgYyeRnmdmsGP1cj\n" + 27 | "Lb8jQckg/1q6lnJvHLq39P8uhAYmNPU7HTojerECgYA1K1w0ZnmXA7+kcT5bT9Yg\n" + 28 | "aNXrK9UwHlZ0zXSrdazb/86oPFdeaBV9K74fluVAMaJRwn/UPri733HCF1Wv4UxW\n" + 29 | "qI7Ejfy0KO7WrZ35iKDY8sFBcT5huktO7KuQ7bdi8HyrgIScRO8QSK7Zu3S5ITpL\n" + 30 | "4PwjhYOAwofSsEQlTkf6/QKBgAR9spQ8dqxi2VsQP0IciRkyd45JaDbqU2nN8Dfv\n" + 31 | "rOwEoJIhwGKr9cehZRDJHD2FqVUgdYFlDXDaL2o1g20/IVXMs2tf8wrxqrhuVEpN\n" + 32 | "HE0j97tYRgziXhdpZ3TfADcSR6PjL4MZpQUbWnP0tM9YO3LMeAfugjM5PVwPst78\n" + 33 | "AeURAoGBANQ0s6p/ZGV9pmteoN452Oz+PHD/WCc1wid9m2eKawqNYRODC6ls1eQ+\n" + 34 | "h1veQozYJLLob3+fVgKiHo/KEtA/4Svq7/+2eW4rBs12C6N+bSBj01no6nmqrDrO\n" + 35 | "j+fOdGjzGxHSiqI8QvKa+9JJodXzfKNT2ALzV/Q7h6OHjsP549Ze\n" + 36 | "-----END RSA PRIVATE KEY-----\n" 37 | } 38 | } -------------------------------------------------------------------------------- /OAuth/Scopes.md: -------------------------------------------------------------------------------- 1 | # OAuth 2.0 Scopes 2 | 3 | OAuth scopes govern the access and privileges an Adobe user will grant authorization to a third-party application for. As an application developer, you will choose the set of scopes that a user will encounter in an authorization approval screen by specifying the scopes as part of the OAuth authorization request. 4 | 5 | 6 | 7 | 8 | 9 | ## Contents 10 | 11 | - [Creative Cloud](#creative-cloud) 12 | - [Experience Cloud](#experience-cloud) 13 | - [Scope Definitions](#scope-definitions) 14 | - [openid](#openid) 15 | - [creative_sdk](#creative_sdk) 16 | 17 | 18 | 19 | ## Creative Cloud 20 | Scopes for Creative Cloud OAuth based APIs 21 | 22 | APIs | Scopes 23 | ---|--- 24 | Adobe Stock | `openid` 25 | Creative SDK | `openid,creative_sdk` 26 | Photoshop | `openid,creative_sdk` 27 | Lightroom | `openid,creative_sdk` 28 | 29 | 30 | 31 | 32 | ## Experience Cloud 33 | Scopes for Experience Cloud OAuth based APIs 34 | 35 | APIs | Scopes 36 | ---|--- 37 | Adobe Analytics | `openid,AdobeID,read_organizations,additional_info.projectedProductContext,additional_info.job_function` 38 | 39 | 40 | 41 | ## Scope Definitions 42 | The scope determines the type of access to protected resources an application can be granted authorization to. Scopes are aggregates of specific attributes. 43 | 44 | ### openid 45 | 46 | One-stop-shop scope for accessing Adobe user profile information. 47 | 48 | |Attribute|User Information Returned| 49 | |---|---| 50 | |userId|Unique ID| 51 | |first_name|Given name| 52 | |last_name|Surname or family name| 53 | |phoneNumber|Telephone number (NULL if unavailable)| 54 | |emailVerified|Verification status of primary email address| 55 | |countryCode|Country component of an ISO2 locale code| 56 | |name|Full name| 57 | |displayName|Display name| 58 | |email|Primary email address| 59 | |preferred_languages|An array of locale codes indicating preferred language settings| 60 | |account_type|The account_type with one of the values: type1 (individual), type2 (enterprise), type3 (federated). See [Adobe Identity Types](https://helpx.adobe.com/enterprise/using/identity.html) for details.| 61 | 62 | ### creative_sdk 63 | 64 | Intended for use specifically with the Creative SDK. This is an extension of the `openid` scope, so the following is a list of attributes *in addition* to what's available in the `openid` scope. 65 | 66 | |Attribute|User Information Returned| 67 | |---|---| 68 | |userId|Unique ID| 69 | |service_accounts|An array of service account objects used to provide permissions to Creative Cloud services| 70 | -------------------------------------------------------------------------------- /Backup/OAuth2.0Endpoints/oauth-scopes.md: -------------------------------------------------------------------------------- 1 | # OAuth 2.0 Scopes 2 | 3 | OAuth scopes govern the access and privileges an Adobe user will grant authorization to a third-party application for. As an application developer, you will choose the set of scopes that a user will encounter in an authorization approval screen by specifying the scopes as part of the OAuth authorization request. 4 | 5 | 6 | 7 | 8 | 9 | ## Contents 10 | 11 | 1. [Creative Cloud](#creative-cloud) 12 | 1. [Experience Cloud](#experience-cloud) 13 | 1. [Scope Definitions](#scope-definitions) 14 | 1. [openid](#openid) 15 | 1. [creative_sdk](#creative_sdk) 16 | 17 | 18 | 19 | ## Creative Cloud 20 | Scopes for Creative Cloud OAuth based APIs 21 | 22 | APIs | Scopes 23 | ---|--- 24 | Adobe Stock | `openid` 25 | Creative SDK | `openid,creative_sdk` 26 | Photoshop | `openid,creative_sdk` 27 | Lightroom | `openid,creative_sdk` 28 | 29 | 30 | 31 | 32 | ## Experience Cloud 33 | Scopes for Experience Cloud OAuth based APIs 34 | 35 | APIs | Scopes 36 | ---|--- 37 | Adobe Analytics | `openid,AdobeID,read_organizations,additional_info.projectedProductContext,additional_info.job_function` 38 | 39 | 40 | 41 | ## Scope Definitions 42 | The scope determines the type of access to protected resources an application can be granted authorization to. Scopes are aggregates of specific attributes. 43 | 44 | ### openid 45 | 46 | One-stop-shop scope for accessing Adobe user profile information. 47 | 48 | |Attribute|User Information Returned| 49 | |---|---| 50 | |userId|Unique ID| 51 | |first_name|Given name| 52 | |last_name|Surname or family name| 53 | |phoneNumber|Telephone number (NULL if unavailable)| 54 | |emailVerified|Verification status of primary email address| 55 | |countryCode|Country component of an ISO2 locale code| 56 | |name|Full name| 57 | |displayName|Display name| 58 | |email|Primary email address| 59 | |preferred_languages|An array of locale codes indicating preferred language settings| 60 | |account_type|The account_type with one of the values: type1 (individual), type2 (enterprise), type3 (federated). See [Adobe Identity Types](https://helpx.adobe.com/enterprise/using/identity.html) for details.| 61 | 62 | ### creative_sdk 63 | 64 | Intended for use specifically with the Creative SDK. This is an extension of the `openid` scope, so the following is a list of attributes *in addition* to what's available in the `openid` scope. 65 | 66 | |Attribute|User Information Returned| 67 | |---|---| 68 | |userId|Unique ID| 69 | |service_accounts|An array of service account objects used to provide permissions to Creative Cloud services| 70 | -------------------------------------------------------------------------------- /AuthenticationOverview/APIKeyIntegration.md: -------------------------------------------------------------------------------- 1 | # API Key Connection 2 | 3 | A small collection of Adobe services (e.g. Adobe Stock) require authorization, but do not require authentication. These services can be called _“anonymously”_ and typically provide consistent results regardless of the application or user that made the request. An **API Key** is the only client credential required for these services. These connections do not need to pass an access token with each request. 4 | 5 | To obtain an API Key, you'll need to create an API Key connection using the Adobe Developer Console. 6 | 7 | > **Note:** If your application needs to access Adobe services or content on behalf of a user or an Adobe enterprise organization, it needs additional credentials for authentication. For more information, read the **[OAuth Authentication](OAuthIntegration.md)** and **[Service Account (JWT) Authentication](ServiceAccountIntegration.md)** documentation. 8 | 9 | This article will walk you through the steps to set up an **API Key** connection. 10 | 11 | ## API Key connection workflow 12 | 13 | [Step 1: Create a project in Adobe Developer Console](#step-1-create-a-project-in-adobe-developer-console) 14 | 15 | [Step 2: Add an API to your project using API Key authorization](#step-2-add-an-api-to-your-project-using-API-Key-authorization) 16 | 17 | [Step 3: Try It](#step-3-try-it) 18 | 19 | ### Step 1: Create a project in Adobe Developer Console 20 | 21 | Integrations are now created as part of a "project" within Adobe Developer Console. For complete steps to creating a project in Console, begin by reading the [Adobe Developer Console getting started guide](https://www.adobe.com/go/devs_console_getting_started) and [projects overview](https://www.adobe.com/go/devs_projects_overview). 22 | 23 | Once you have created a project, you will be able to add services including APIs, I/O Events, and I/O Runtime. 24 | 25 | ### Step 2: Add an API to your project using API Key authorization 26 | 27 | To add an API that uses API Key authorization, follow the steps outlined in the guide for [adding an API to a project using API Key authorization](https://www.adobe.com/go/devs_projects_api_key). 28 | 29 | When the API has been successfully connected, you will be able to access the newly generated API Key. 30 | 31 | ### Step 3: Try It 32 | 33 | Copy the API Key from the Adobe Developer Console project and replace `myAPIKey` in the sample request below. 34 | 35 | ```curl 36 | curl 'https://stock.adobe.io/Rest/Media/1/Search/Files?locale=en_US%26search_parameters%5Bwords%5D=kittens ' 37 | -H 'x-api-key:myAPIKey' 38 | -H 'x-product:myTestApp1.0' 39 | ``` 40 | 41 | Open Postman and go to `Import`->`Paste Raw Text` and paste the curl command. Select **Import** to import it. 42 | 43 | ![api-key-5](../Images/api-key-5.png) 44 | 45 | Select **Send**. You will receive a successful response. Note that you did not need an access token in order to make a successful request using API Key integration. 46 | 47 | ![api-key-7](../Images/api-key-7.png) 48 | -------------------------------------------------------------------------------- /Backup/idTypes.md: -------------------------------------------------------------------------------- 1 | # Adobe-supported identity types 2 | 3 | Adobe uses an underlying identity management system to authenticate and authorize users. If you're using named licensing or are planning to provide access to services, using identities is a requirement. Adobe supports three identity or account types; they use an email address as the user name. 4 | 5 | ## Adobe ID (Type 1) 6 | Adobe ID is created, owned, and managed by the end user. Adobe performs the authentication and the end user manages the identity. Users retain complete control over files and data associated with their ID. Users can purchase additional products and services from Adobe. Admins invite users to join the organization, and can remove them. However, users cannot be locked out from their Adobe ID accounts. The admin can't delete or take over the accounts. No setup is necessary before you can start using Adobe IDs. 7 | 8 | Adobe recommends Adobe IDs for the following requirements: 9 | 10 | * To enable users to create, own, and manage their identities. 11 | * To allow users to purchase or sign up for other Adobe products and services. 12 | * When users are expected to use other Adobe services, which do not currently support Enterprise or Federated IDs. 13 | * When users already have Adobe IDs, and associated data such as files, fonts, or settings. 14 | * In Higher Education settings so that adult students can easily retain the same Adobe ID and account content upon graduation. 15 | * If you have contractors and freelancers who do not use email addresses on domains you control. 16 | 17 | ## Enterprise ID (Type 2) 18 | Enterprise ID is created, owned, and managed by an organization. Adobe hosts the Enterprise ID and performs authentication, but the organization maintains the Enterprise ID. End users cannot sign up and create an Enterprise ID, nor can they sign up for additional products and services from Adobe using an Enterprise ID. 19 | 20 | Admins create an Enterprise ID and issue it to a user. Admins can revoke access to products and services by taking over the account, or deleting the Enterprise ID to permanently block access to associated data. 21 | 22 | Adobe recommends Enterprise IDs for the following requirements: 23 | 24 | * To maintain strict control over apps and services available to a user. 25 | * For emergency access to files and data associated with an ID. 26 | * To have the ability to completely block or delete a user account. 27 | * In all K-12 user settings to ensure compliance with student privacy and other relevant laws. 28 | 29 | ## Federated ID (Type 3) 30 | Federated ID is created and owned by an organization, and linked to the enterprise directory via federation. The organization manages credentials and processes Single Sign-On via a SAML2 Identity Provider (IdP). 31 | 32 | Adobe recommends Federated IDs for the following requirements: 33 | 34 | * To provision users based on your organization's enterprise directory. 35 | * To manage authentication of users. 36 | * To maintain strict control over apps and services available to a user. 37 | * To allow users to use the same email address to sign up for an Adobe ID. 38 | * In all K-12 user settings to ensure compliance with student privacy and other relevant laws. -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Adobe Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at Grp-opensourceoffice@adobe.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [https://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: https://contributor-covenant.org 74 | [version]: https://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /OAuth/samples/adobe-auth-python/adobe-oauth2.0.py: -------------------------------------------------------------------------------- 1 | import os 2 | import flask 3 | import requests 4 | from six.moves import urllib 5 | import json 6 | 7 | # Start flask app 8 | app = flask.Flask(__name__) 9 | 10 | # Load config object from config.py 11 | app.config.from_object('config.Config') 12 | 13 | # Loading FLAST_SECRET from config.py 14 | app.secret_key = app.config['FLASK_SECRET'] 15 | 16 | @app.route('/') 17 | def home(): 18 | return flask.render_template('index.html') 19 | 20 | @app.route('/authorize') 21 | def authorize(): 22 | # Adobe OAuth2.0 authorization url 23 | authorization_url = 'https://ims-na1.adobelogin.com/ims/authorize?' 24 | 25 | # Store required parameters in a dictionary 26 | params = { 27 | 'client_id' : app.config['ADOBE_API_KEY'], 28 | 'scope' : 'openid,creative_sdk', 29 | 'response_type' : 'code', 30 | 'redirect_uri' : flask.url_for('callback', _external=True) 31 | } 32 | 33 | # This will prompt users with the approval page if consent has not been given 34 | # Once permission is provided, users will be redirected to the specified page 35 | return flask.redirect(authorization_url + urllib.parse.urlencode(params)) 36 | 37 | @app.route('/callback') 38 | def callback(): 39 | # Retrive the authorization code from callback 40 | authorization_code = flask.request.args.get('code') 41 | 42 | # Adobe OAuth2.0 token url 43 | token_url = 'https://ims-na1.adobelogin.com/ims/token' 44 | 45 | # Store required parameters in a dictionary 46 | # And include the authorization code in it 47 | params = { 48 | 'grant_type' : 'authorization_code', 49 | 'client_id' : app.config['ADOBE_API_KEY'], 50 | 'client_secret' : app.config['ADOBE_API_SECRET'], 51 | 'code' : authorization_code 52 | } 53 | 54 | # Use requests library to send the POST request 55 | response = requests.post(token_url, 56 | params = params, 57 | headers = {'content-type': 'application/x-www-form-urlencoded'}) 58 | 59 | # After receiving a 'OK' response, 60 | if response.status_code == 200: 61 | # save credentials to session 62 | flask.session['credentials'] = response.json() 63 | return flask.render_template('index.html', response='login success') 64 | else: 65 | return flask.render_template('index.html', response='login failed') 66 | 67 | @app.route('/profile') 68 | def profile(): 69 | # Check if credentials exist. If not, ask the user to log in 70 | if 'credentials' not in flask.session: 71 | return flask.render_template('index.html', response='Please log in first') 72 | else: 73 | # Retrive the access token from the flask session 74 | access_token = flask.session['credentials']['access_token'] 75 | 76 | # Adobe OAuth2.0 profile url 77 | profile_url = 'https://ims-na1.adobelogin.com/ims/userinfo' 78 | 79 | # Store required parameters in a dictionary 80 | params = { 81 | 'client_id' : app.config['ADOBE_API_KEY'] 82 | } 83 | 84 | # Use requests library to send the GET request 85 | response = requests.get(profile_url, 86 | params = params, 87 | headers = {'Authorization': 'Bearer {}'.format(access_token)}) 88 | 89 | if response.status_code == 200: 90 | return flask.render_template('index.html', response=json.dumps(response.json())) 91 | else: 92 | return flask.render_template('index.html', response='profile could not be retrieved') 93 | 94 | if __name__ == '__main__': 95 | # Make sure the hostname and port you provide match the valid redirect URI 96 | # specified in your project in the Adobe developer Console. 97 | # Also, make sure to have `cert.pem` and `key.pem` in your directory 98 | app.run('localhost', 8000, debug=True, ssl_context=('cert.pem', 'key.pem')) -------------------------------------------------------------------------------- /JWT/samples/adobe-jwt-dotnet/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography.X509Certificates; 3 | using Jose; 4 | using RestSharp; 5 | using System.Collections.Generic; 6 | 7 | //NuGet packages: Jose and RestSharp 8 | 9 | namespace adobe_jwt_dotnet 10 | { 11 | class Program 12 | { 13 | static void Main(string[] args) 14 | { 15 | //Copy these details from console.adobe.io integration 16 | const string CLIENT_ID = "YOUR API KEY (CLIENT ID)"; //e.g. ......328adcb8062d 17 | const string CLIENT_SECRET = "YOUR CLIENT SECRET"; //e.g. ......-ad95-70e50b6b4ea3 18 | const string TECH_ACC_ID = "YOUR TECHNICAL ACCOUNT ID"; //e.g. ......0A495C2A@techacct.adobe.com 19 | const string ORG_ID = "YOUR ORGANIZATION ID"; //e.g. ......0A495D09@AdobeOrg 20 | const string METASCOPES = "YOUR METASCOPES IN COMMA SEPARATED FORMAT"; //e.g. "https://ims-na1.adobelogin.com/s/ent_reactor_developer_sdk,https://ims-na1.adobelogin.com/s/ent_reactor_admin_sdk" 21 | 22 | 23 | Dictionary test = new Dictionary(); 24 | test.Add("exp", DateTimeOffset.Now.ToUnixTimeSeconds()+600); 25 | test.Add("iss", ORG_ID); 26 | test.Add("sub", TECH_ACC_ID); 27 | test.Add("aud", "https://ims-na1.adobelogin.com/c/"+CLIENT_ID); 28 | string[] scopes = METASCOPES.Split(','); 29 | 30 | foreach(string scope in scopes) 31 | { 32 | test.Add(scope, true); 33 | } 34 | 35 | //You must have generated a certificate using below command and uploaded in the console.adobe.io integration 36 | //openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout private.key -out certificate_pub.crt 37 | 38 | //Create a pfx file using the private key and public certificate generated from the above step 39 | //openssl pkcs12 -export -out mycert.pfx -inkey private.key -in certificate_pub.crt 40 | //Enter export password: password 41 | 42 | try 43 | { 44 | X509Certificate2 cert = new X509Certificate2("/path/to/mycert.pfx", "password"); 45 | 46 | string token = Jose.JWT.Encode(test, cert.GetRSAPrivateKey(), JwsAlgorithm.RS256); 47 | 48 | Console.WriteLine(token); //Intermediate JWT Token 49 | 50 | var client = new RestClient("https://ims-na1.adobelogin.com/ims/exchange/jwt/"); 51 | 52 | var request = new RestRequest(Method.POST); 53 | request.AddHeader("cache-control", "no-cache"); 54 | request.AddHeader("content-type", "multipart/form-data; boundary=----boundary"); 55 | request.AddParameter("multipart/form-data; boundary=----boundary", 56 | "------boundary\r\nContent-Disposition: form-data; name=\"client_id\"\r\n\r\n" + CLIENT_ID + 57 | "\r\n------boundary\r\nContent-Disposition: form-data; name=\"client_secret\"\r\n\r\n" + CLIENT_SECRET + 58 | "\r\n------boundary\r\nContent-Disposition: form-data; name=\"jwt_token\"\r\n\r\n" + token + 59 | "\r\n------boundary--", ParameterType.RequestBody); 60 | 61 | 62 | IRestResponse response = client.Execute(request); 63 | 64 | Console.WriteLine(response.Content); 65 | } 66 | catch(Exception e) 67 | { 68 | Console.WriteLine("An error has occured: "+e.Message); 69 | } 70 | 71 | 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /OAuth/samples/adobe-auth-node/server/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | const session = require('express-session') 4 | const { default: axios } = require('axios'); 5 | 6 | /* Dependencies for setting up https server */ 7 | const https = require('https'); 8 | const fs = require('fs'); 9 | const path = require('path'); 10 | 11 | /* Declare host name and port */ 12 | const hostname = 'localhost'; 13 | const port = 8000; 14 | 15 | /* Variables needed for authorization */ 16 | const scopes = 'openid,creative_sdk,profile,address,AdobeID,email,offline_access' 17 | const redirect_uri = 'https://localhost:8000/callback/' 18 | 19 | /* Configuring client application credentials stored in .env file */ 20 | require('dotenv').config(); 21 | const adobeApiKey = process.env.API_KEY; 22 | const adobeApiSecret = process.env.API_SECRET; 23 | 24 | /* Middlewares */ 25 | app.use(express.static(path.join(__dirname, '../public'))); 26 | app.set('views', path.join(__dirname, '../views')) 27 | app.set('view engine', 'pug') 28 | app.use(session({ 29 | secret: 'secret-value-123', 30 | resave: false, 31 | saveUninitialized: true, 32 | cookie: { 33 | maxAge: 6000000 34 | } 35 | })); 36 | 37 | /* Routes */ 38 | app.get('/', function (req, res) { 39 | res.render('index'); 40 | }) 41 | 42 | app.get('/login', function(req, res){ 43 | /* This will prompt user with the Adobe auth screen */ 44 | res.redirect(`https://ims-na1.adobelogin.com/ims/authorize/v2?client_id=${adobeApiKey}&scope=${scopes}&response_type=code&redirect_uri=${redirect_uri}`) 45 | }) 46 | 47 | app.get('/callback', async function(req, res){ 48 | /* Retrieve authorization code from request */ 49 | let code = req.query.code; 50 | let uri = `https://ims-na1.adobelogin.com/ims/token/v3?grant_type=authorization_code&client_id=${adobeApiKey}&client_secret=${adobeApiSecret}&code=${code}`; 51 | axios.post(uri) 52 | .then(function(response){ 53 | req.session.token = response.data.access_token; 54 | res.render('index', {'response': 'User logged in!'}); 55 | }) 56 | .catch(function (error){ 57 | console.log(error); 58 | res.render('index', {'response':'Log in failed!'}) 59 | }) 60 | }) 61 | 62 | app.get('/profile', async function(req, res){ 63 | let uri = `https://ims-na1.adobelogin.com/ims/userinfo/v2?client_id=${adobeApiKey}`; 64 | let options = { 65 | headers: { 66 | "x-api-key": process.env.API_KEY, 67 | Authorization: `Bearer ${req.session.token}`, 68 | },}; 69 | if (req.session.token) { 70 | axios.get(uri, options) 71 | .then(function (response){ 72 | res.render('index', {'response': JSON.stringify(response.data)}); 73 | }) 74 | .catch(function (error){ 75 | console.log(error); 76 | }) 77 | } 78 | else{ 79 | res.render('index', {'response':'You need to log in first'}); 80 | } 81 | }) 82 | 83 | app.get('/logout', function(req, res){ 84 | if (req.session) { 85 | req.session.destroy(err => { 86 | if (err){ 87 | res.render('index', {'response': 'Unable to log out'}); 88 | } else{ 89 | res.render('index', {'response': 'Logout successful!'}) 90 | } 91 | }); 92 | } else { 93 | res.render('index', {'response': 'Token not stored in session'}) 94 | } 95 | }); 96 | 97 | 98 | /* Set up a HTTPS server with the signed certification */ 99 | var httpsServer = https.createServer({ 100 | key: fs.readFileSync(path.join(__dirname,'./localhost-key.pem')), 101 | cert: fs.readFileSync(path.join(__dirname, './localhost.pem')) 102 | }, app).listen(port, hostname, (err) => { 103 | if (err) console.log(`Error: ${err}`); 104 | console.log(`listening on port ${port}!`); 105 | }); -------------------------------------------------------------------------------- /Resources/Tools/Postman.md: -------------------------------------------------------------------------------- 1 | # Postman 2 | 3 | ## Contents 4 | 5 | - [OAuth Access Token](#oauth-access-token) 6 | - [JWT Access Token](#jwt-access-token) 7 | - [CURL Requests in Windows](#curl-requests-in-windows) 8 | 9 | ## OAuth Access Token 10 | 11 | ### Steps 12 | 13 | 1. Install [Postman](https://www.getpostman.com/downloads/) 14 | 15 | 2. Open Postman 16 | 17 | 3. Create a `new request`. 18 | 19 | ![pm-1](../../Images/PM_1.png) 20 | 21 | 4. Click on `Authorization` and select `OAuth 2.0` from Type dropdown menu. 22 | 23 | ![pm-2](../../Images/PM_2.png) 24 | 25 | 5. Click on `Get New Access Token`. 26 | 27 | ![pm-3](../../Images/PM_3.png) 28 | 29 | 6. Copy your `API Key (Client ID)`, `Client Secret` and the `Default Redirect URI` from your Adobe Developer Console integration and paste it in the Postman `GET NEW ACCESS TOKEN` window. Assuming you are trying to get an access token for Adobe Analytics use below for scope: 30 | ``` 31 | openid,AdobeID,read_organizations,additional_info.projectedProductContext,additional_info.job_function 32 | ``` 33 | 34 | *Note: If you are not sure about scope, refer to [Scope Reference](../../OAuth/Scopes.md).* 35 | 36 | ![pm-4](../../Images/PM_4.png) 37 | 38 | 7. You will be prompted for login by Adobe. Login using your Adobe ID. 39 | 40 | ![pm-5](../../Images/PM_5.png) 41 | 42 | 8. Your access token will be generated. 43 | 44 | ![pm-6](../../Images/PM_6.png) 45 | 46 | ## JWT Access Token 47 | ### Steps 48 | 1. Go to [Adobe Developer Console](https://www.adobe.com/go/devs_console_ui) 49 | 50 | 2. Open the Service Account Integration for which you want to generate an access token. 51 | 52 | ![pmj-1](../../Images/PM_JWT_1.png) 53 | 54 | 3. Click on the JWT tab, paste the entire private key file content including the `-----BEGIN PRIVATE KEY-----` and `-----END PRIVATE KEY-----` and click on `Generate JWT`. 55 | 56 | ![pmj-2](../../Images/PM_JWT_2.png) 57 | 58 | 4. Copy the `Sample CURL command` and open Postman. (*Mac and Linux user can also paste the CURL command in terminal and get the access token.*) 59 | 60 | ![pmj-3](../../Images/PM_JWT_3.png) 61 | 62 | 5. Click on `Import` -> `Paste Raw Text` and paste the CURL command. 63 | 64 | ![pmj-4](../../Images/PM_JWT_4.png) 65 | 66 | 6. Click on `Send`. You will receive an access token. 67 | 68 | ![pmj-5](../../Images/PM_JWT_5.png) 69 | 70 | ## CURL Requests in Windows 71 | 72 | In API Documentation, sample CURL requests are common and helpful for the developers. Mac and Linux terminals are capable of executing such CURL requests but the Windows command prompt doesn't support it out of the box. 73 | 74 | For windows users, you can follow below steps to execute the CURL requests easily by using Postman. 75 | 76 | ### Steps 77 | 78 | 1. Copy the CURL Request. 79 | e.g. 80 | ``` 81 | curl https://stock.adobe.io/Rest/Media/1/Search/Files?locale=en_US%26search_parameters%5Bwords%5D=kittens 82 | -H 'x-api-key:myAPIKey' 83 | -H 'x-product:myTestApp1.0' 84 | ``` 85 | 86 | 2. Open Postman. Click `Import` -> `Paste Raw Text` -> Paste the CURL request. 87 | 88 | ![pmw-1](../../Images/PMW_1.png) 89 | 90 | 3. Go to `Headers` tab and replace `myAPIKey` with your actual API Key from Adobe Developer Console integration for Adobe Stock. 91 | 92 | ![pmw-2](../../Images/PMW_2.png) 93 | 94 | 4. Click Send. You will receive a response. 95 | 96 | ![pmw-3](../../Images/PMW_3.png) 97 | 98 | *Note: You can import any CURL Request into Postman by following the above steps.* 99 | 100 | -------------------------------------------------------------------------------- /OAuth/samples/adobe-auth-python/readme.md: -------------------------------------------------------------------------------- 1 | # OAuth 2.0 Example: Python 2 | 3 | This sample app will show you how to implement Adobe OAuth 2.0 in Python using the Flask framework. 4 | 5 | After setting up the sample, you will have a Python app that: 6 | 7 | 1. Serves `templates/index.html` on `https://localhost:8000` 8 | 1. Lets a user log in with their Adobe ID 9 | 1. Prompts the user to authorize the app with requested scopes 10 | 1. Lets the user view their Adobe ID profile information 11 | 1. Lets the user log out 12 | 13 | 14 | 15 | 16 | ## Contents 17 | 18 | - [OAuth 2.0 Example: Python](#oauth-20-example-python) 19 | - [Contents](#contents) 20 | - [Technology Used](#technology-used) 21 | - [Prerequisites](#prerequisites) 22 | - [Configuration](#configuration) 23 | - [Create an OpenSSL cert](#create-an-openssl-cert) 24 | - [Install Python libraries](#install-python-libraries) 25 | - [Enter your Flask secret and Adobe API credentials](#enter-your-flask-secret-and--adobe-api-credentials) 26 | - [Usage](#usage) 27 | - [Other Resources](#other-resources) 28 | 29 | 30 | 31 | ## Technology Used 32 | 33 | 1. Python 2.6 or greater and the `pip` package manager 34 | 1. OpenSSL CLI 35 | 36 | 37 | ## Prerequisites 38 | 39 | This guide will assume that you have read the [Adobe OAuth 2.0 Guide for Web](../../../Backup/OAuth2.0Endpoints/web-oauth2.0-guide.md). 40 | 41 | You must also have [a registered app on the Adobe Developer Console](../../../Backup/OAuth2.0Endpoints/web-oauth2.0-guide.md#register-your-application-and-enable-apis) with the following settings: 42 | 43 | 1. `Platform`: web 44 | 1. `Default redirect URI`: `https://localhost:8000` 45 | 1. `Redirect URI Pattern`: `https://localhost:8000` 46 | 47 | 48 | ## Configuration 49 | 50 | The following steps will help you get this sample up and running. 51 | 52 | 53 | ### Create an OpenSSL cert 54 | 55 | Adobe OAuth 2.0 requires SSL, so you will need to create a self-signed cert using the OpenSSL CLI: 56 | 57 | ``` 58 | $ openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365 59 | ``` 60 | 61 | Make sure that after running this command you have the `cert.pem` and `key.pem` files at the top level of the sample app. 62 | 63 | 64 | ### Install Python libraries 65 | 66 | This sample app uses the [Flask](http://flask.pocoo.org/), [Requests](http://docs.python-requests.org/), and [Six](https://pythonhosted.org/six/) libraries. You can install them using the `pip` package manager: 67 | 68 | ``` 69 | $ pip install flask 70 | $ pip install requests 71 | $ pip install six 72 | ``` 73 | 74 | 75 | ### Enter your Flask secret and Adobe API credentials 76 | 77 | Enter the required credentials in `config.py`: 78 | 79 | ``` 80 | class Config(object): 81 | FLASK_SECRET = 'PLACEHOLDER_SECRET_KEY' 82 | ADOBE_API_KEY = 'YOUR_ADOBE_KEY' 83 | ADOBE_API_SECRET = 'YOUR_ADOBE_SECRET' 84 | ``` 85 | 86 | You can get your Adobe API Key and Secret from your registered app page on the [Adobe Developer Console](../../../Backup/OAuth2.0Endpoints/web-oauth2.0-guide.md#register-your-application-and-enable-apis). 87 | 88 | 89 | ## Usage 90 | 91 | After completing the configuration steps, run `adobe-oauth2.0.py`: 92 | 93 | ``` 94 | $ python adobe-oauth2.0.py 95 | ``` 96 | 97 | To access the app, go to `https://localhost:8000`. Click through any cert warnings in the browser. 98 | 99 | 100 | ## Other Resources 101 | 102 | - [Adobe OAuth 2.0 Guide for Web](../../../Backup/OAuth2.0Endpoints/web-oauth2.0-guide.md) 103 | -------------------------------------------------------------------------------- /AuthenticationOverview/ServiceAccountIntegration.md: -------------------------------------------------------------------------------- 1 | # Service Account Connection 2 | 3 | A Service Account connection allows your application to call Adobe services on behalf of the application itself or on behalf of an enterprise organization. 4 | 5 | For this type of connection, you will create a JSON Web Token (JWT) that encapsulates your credentials and begin each API session by exchanging the JWT for an access token. 6 | 7 | The JWT encodes all of the identity and security information required to obtain an access token and must be signed with the private key that is associated with a public key certificate specified on your integration. 8 | 9 | This article walks you through the steps to set up a **Service Account** connection. 10 | 11 | ## Service Account connection workflow 12 | 13 | [Step 1: Create a project in Adobe Developer Console](#step-1-create-a-project-in-adobe-developer-console) 14 | 15 | [Step 2: Add an API to your project using Service Account (JWT) authentication](#step-2-add-an-api-to-your-project-using-service-account-authentication) 16 | 17 | [Step 3: Try It](#step-3-try-it) 18 | 19 | ### Step 1: Create a project in Adobe Developer Console 20 | 21 | Integrations are now created as part of a "project" within Adobe Developer Console. For complete steps to creating a project in Console, begin by reading the [Adobe Developer Console getting started guide](https://www.adobe.com/go/devs_console_getting_started) and [projects overview](https://www.adobe.com/go/devs_projects_overview). 22 | 23 | Once you have created a project, you will be able to add services including APIs, Adobe I/O Events registrations, and Adobe I/O Runtime. 24 | 25 | ### Step 2: Add an API to your project using Service Account authentication 26 | 27 | To add an API that uses Service Account (JWT) authentication, follow the steps outlined in the guide for [adding an API to a project using Service Account authentication](https://www.adobe.com/go/devs_projects_jwt). 28 | 29 | During the API configuration process, you will be able to generate a key pair and download the private key. 30 | 31 | When the API has been successfully connected, you will be able to access the newly generated credentials including Client ID and Client Secret, as well as generate an access token using the private key that you generated during configuration. 32 | 33 | ### Step 3: Try It 34 | 35 | In order to try out the connection, follow the steps in the [Adobe Developer Console credentials guide](https://www.adobe.com/go/devs_console_credentials) for generating a JWT token and copy the *Sample cURL command* provided. 36 | 37 | Next, open Postman and select Import > Paste Raw Text and paste the copied curl command. Select **Import** to continue. 38 | 39 | ![Postman import](../Images/auth_jwtqs_07.png "Postman import") 40 | 41 | With the command imported, select **Send** to execute. 42 | 43 | ![Postman send](../Images/auth_jwtqs_08.png "Postman send") 44 | 45 | The example curl sends a POST request to [https://ims-na1.adobelogin.com/ims/exchange/jwt](https://ims-na1.adobelogin.com/ims/exchange/jwt) using the parameters outlined in the table below. 46 | 47 | The response body includes your newly generated access token (`access_token`). 48 | 49 | | Parameter | Description| 50 | |---|---| 51 | | `client_id` | The Client ID provided in Console as part of the *Credential details*. | 52 | | `client_secret` | The Client Secret provided in Console as part of the *Credential details*. | 53 | | `jwt_token` | A base-64 encoded JSON Web Token that encapsulates the identity of your connection, signed with a private key that corresponds to a public key certificate attached to the connection. This token can be generated in Console from the *Generate JWT* tab within *Credentials*. Note that this token has the expiration time parameter `exp` set to 24 hours from when the token is generated. | 54 | 55 | > **Note:** Check the documentation for the specific API service for which you’re hitting authenticated endpoints to find what other parameters are expected. Most of them need an `x-api-key`, which will be the same as your `client_id`. 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Authentication", 3 | "version": "1.0.0", 4 | "description": "Authentication", 5 | "author": "Hiren Shah", 6 | "view_type": "mdbook", 7 | "meta_keywords": "adobe i/o, authentication", 8 | "meta_description": "default description", 9 | "publish_date": "02/08/2019", 10 | "show_edit_github_banner": false, 11 | "base_path": "https://raw.githubusercontent.com", 12 | "pages": [ 13 | { 14 | "importedFileName": "Authentication Overview", 15 | "path": "AdobeDocs/adobeio-auth/stage/AuthenticationOverview/AuthenticationGuide.md", 16 | "title": "Authentication Overview", 17 | "pages": [ 18 | { 19 | "importedFileName": "API Key Integration", 20 | "pages": [], 21 | "path": "AdobeDocs/adobeio-auth/stage/AuthenticationOverview/APIKeyIntegration.md", 22 | "title": "API Key Integration" 23 | }, 24 | { 25 | "importedFileName": "OAuth Integration", 26 | "pages": [], 27 | "path": "AdobeDocs/adobeio-auth/stage/AuthenticationOverview/OAuthIntegration.md", 28 | "title": "OAuth Integration" 29 | }, 30 | { 31 | "importedFileName": "Service Account Integration", 32 | "pages": [], 33 | "path": "AdobeDocs/adobeio-auth/stage/AuthenticationOverview/ServiceAccountIntegration.md", 34 | "title": "Service Account Integration" 35 | } 36 | ] 37 | }, 38 | { 39 | "importedFileName": "OAuth Authentication", 40 | "pages": [ 41 | { 42 | "importedFileName": "OAuth Scopes", 43 | "pages": [], 44 | "path": "AdobeDocs/adobeio-auth/stage/OAuth/Scopes.md", 45 | "title": "OAuth Scopes" 46 | }, 47 | { 48 | "importedFileName": "OAuth Sample Code", 49 | "pages": [], 50 | "path": "AdobeDocs/adobeio-auth/stage/OAuth/samples/samples.md", 51 | "title": "OAuth Sample Code" 52 | } 53 | ], 54 | "path": "AdobeDocs/adobeio-auth/stage/OAuth/OAuth.md", 55 | "title": "OAuth Authentication" 56 | }, 57 | { 58 | "importedFileName": "JWT (Service Account) Authentication", 59 | "pages": [ 60 | { 61 | "importedFileName": "Create a Public Key Certificate", 62 | "pages": [], 63 | "path": "AdobeDocs/adobeio-auth/stage/JWT/JWTCertificate.md", 64 | "title": "Create a Public Key Certificate" 65 | }, 66 | { 67 | "importedFileName": "JWT Metascopes", 68 | "pages": [], 69 | "path": "AdobeDocs/adobeio-auth/stage/JWT/Scopes.md", 70 | "title": "JWT Metascopes" 71 | }, 72 | { 73 | "importedFileName": "JWT Sample Code", 74 | "pages": [], 75 | "path": "AdobeDocs/adobeio-auth/stage/JWT/samples/samples.md", 76 | "title": "JWT Sample Code" 77 | } 78 | ], 79 | "path": "AdobeDocs/adobeio-auth/stage/JWT/JWT.md", 80 | "title": "JWT (Service Account) Authentication" 81 | }, 82 | { 83 | "importedFileName": "Tools", 84 | "pages": [ 85 | { 86 | "importedFileName": "OAuth 2.0 Playground", 87 | "pages": [], 88 | "path": "AdobeDocs/adobeio-auth/stage/Resources/Tools/OAuthPlayground.md", 89 | "title": "OAuth 2.0 Playground" 90 | }, 91 | { 92 | "importedFileName": "Postman", 93 | "pages": [], 94 | "path": "AdobeDocs/adobeio-auth/stage/Resources/Tools/Postman.md", 95 | "title": "Postman" 96 | } 97 | ], 98 | "path": "AdobeDocs/adobeio-auth/stage/Resources/Tools/ToolsOverview.md", 99 | "title": "Tools" 100 | }, 101 | { 102 | "importedFileName": "IMS APIs", 103 | "pages": [], 104 | "path": "AdobeDocs/adobeio-auth/stage/Resources/IMS.md", 105 | "title": "IMS APIs" 106 | }, 107 | { 108 | "importedFileName": "FAQs", 109 | "pages": [], 110 | "path": "AdobeDocs/adobeio-auth/stage/FAQ/Index.md", 111 | "title": "FAQ" 112 | }, 113 | { 114 | "importedFileName": "Support", 115 | "pages": [], 116 | "path": "AdobeDocs/adobeio-auth/stage/Support/Index.md", 117 | "title": "Support" 118 | } 119 | ] 120 | } 121 | -------------------------------------------------------------------------------- /Resources/IMS.md: -------------------------------------------------------------------------------- 1 | # IMS APIs 2 | 3 | Here is a list of Adobe Identity Management Services (IMS) APIs, which can be useful for specific use cases. 4 | 5 | ## Logout 6 | 7 | Invalidates the user's access token, as well as the refresh token (if any), and the related SSO Renga token (if any). It might or might not redirect the user agent, depending on usage. 8 | 9 | Request method | GET or POST 10 | ---- | ---- 11 | Authorization required | User access token and client ID for front-channel request Client ID and secret for back-channel request 12 | Available versions | `ims-na1.adobelogin.com/ims/logout/v1` `ims-na1.adobelogin.com/ims/logout/v1/token` 13 | 14 | ### Request syntax for front-channel logout 15 | 16 | Request method | GET 17 | ---- | ---- 18 | Authorization required | Access token 19 | Available versions | /ims/logout/v1 20 | 21 | Query Parameters | | 22 | ---- | ---- 23 | client_id | Your IMS client ID, assigned on registration. 24 | redirect_uri | A URL to which the user agent is redirected on successful logout. 25 | access_token | Optional, the user's base-64 encoded access token. If specified and still valid, IMS attempts to revoke this token. 26 | callback | Optional, a JavaScript callback function to handle the JSONP response. If not provided, the body of the successful response contains the requested data in JSON format. 27 | 28 | #### Example 29 | ``` 30 | GET /ims/logout/v1?redirect_uri=REDIRECT_URI&access_token=ACCESS_TOKEN&client_id=CLIENT_ID HTTP/1.1 31 | Host: ims-na1.adobelogin.com 32 | 33 | ``` 34 | After internal redirects, IMS redirects the user agent back to the supplied redirect_uri location. 35 | 36 | **Success response** 37 | ``` 38 | HTTP/1.1 302 Moved Temporarily 39 | Cache-Control: no-store 40 | Location: REDIRECT_URI 41 | ``` 42 | 43 | ### Request syntax for back-channel logout with redirect 44 | 45 | Request method | GET / POST 46 | ---- | ---- 47 | Authorization required | Client ID and secret 48 | Available versions | /ims/logout/v1 49 | 50 | Query Parameters | | 51 | ---- | ---- 52 | client_id | Your IMS client ID, assigned on registration. 53 | client_secret | The IMS client-secret credential, assigned on registration. 54 | redirect_uri | A URL to which the user agent is redirected on successful logout. 55 | access_token | Optional, the user's base-64 encoded access token. If specified and still valid, IMS attempts to revoke this token. 56 | callback | Optional, a JavaScript callback function to handle the JSONP response. If not provided, the body of the successful response contains the requested data in JSON format. 57 | 58 | #### Example 59 | ``` 60 | GET /ims/logout/v1?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&access_token=ACCESS_TOKEN HTTP/1.1 61 | Host: ims-na1.adobelogin.com 62 | ``` 63 | **Success response** 64 | ``` 65 | HTTP/1.1 200 66 | Cache-Control: no-store 67 | ``` 68 | 69 | ### Request syntax for non-redirect logout 70 | 71 | Request method | GET / POST 72 | ---- | ---- 73 | Authorization required | Access token 74 | Available versions | /ims/logout/v1/token 75 | 76 | Query Parameters | | 77 | ---- | ---- 78 | access_token | Optional, the user's base-64 encoded access token. If specified and still valid, IMS attempts to revoke this token. 79 | client_id | Mandatory for front-channel CORS requests, optional for front-channel JSONP requests. 80 | callback | Optional, a JavaScript callback function to handle the JSONP response. If not provided, the body of the successful response contains the requested data in JSON format. 81 | 82 | #### Example 83 | 84 | Request using JSONP 85 | ``` 86 | GET /ims/logout/v1/token?access_token=ACCESS_TOKEN&callback=callbackName HTTP/1.1 87 | Host: adobeid-na1.services.adobe.com 88 | Cookie: rm=COOKIE; WCDServer=renga*RENGA_TOKEN 89 | ``` 90 | **Success response** 91 | ``` 92 | HTTP/1.1 200 OK 93 | Set-Cookie: rm=; Domain=.adobe.com; Expires=Wed, 22-Aug-2012 10:35:00 GMT; Path=/; Secure; HttpOnly 94 | Cache-Control: no-store 95 | P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA" 96 | X-RHH: 571465EA68BC81FCFBB6A429B6166882 97 | Set-Cookie: WCDServer=""; Domain=.adobe.com; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/; Secure 98 | Set-Cookie: RengaRMT=""; Domain=.adobe.com; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/; Secure 99 | Content-Type: application/javascript;charset=UTF-8 100 | Transfer-Encoding: chunked 101 | Content-Encoding: gzip 102 | Vary: Accept-Encoding 103 | Date: Wed, 22 Aug 2012 10:35:00 GMT 104 | Server: ASIT 105 | 106 | callbackName({}); 107 | ``` 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /Backup/JWTAuthenticationQuickStart.md: -------------------------------------------------------------------------------- 1 | # JWT Authentication Quick Start 2 | 3 | 4 | API services tied to entitled Adobe products (such as Campaign, Target, Launch, and others) require a JSON Web Token (JWT) to retrieve access tokens for usage against authenticated endpoints. This document serves as a quickstart guide for first-time users. 5 | 6 | ## Things to check before you start: 7 | 8 | You must be an organizational admin for your enterprise organization with the appropriate Adobe products entitled. (Check at https://adminconsole.adobe.com/{your\_org\_id}@AdobeOrg/overview) 9 | 10 | ## Steps to get a JWT and an access token 11 | 12 | Regardless of your platform, you begin with the same steps in Adobe Developer Console: 13 | 14 | 1. Create a new integration in Adobe Developer Console: [https://www.adobe.com/go/devs_console_ui/integrations](https://www.adobe.com/go/devs_console_ui/integrations) 15 | ![Create integration](Images/auth_jwtqs_01.png "Create an integration") 16 | 17 | 2. Choose to access an API. 18 | 19 | 3. Subscribe to an entitled product (for instance, Launch, by Adobe). 20 | ![Subscribe service](Images/auth_jwtqs_02.png "Subscribe to a product or service") 21 | 22 | 4. Confirm that you want to create a new integration. 23 | 24 | 5. Create a private key and a public certificate. Make sure you store these securely. 25 | 26 | Once you complete the above steps, your path diverges depending on your platform: 27 | 28 | _**MacOS and Linux:**_ 29 | 30 | Open a terminal and execute the following command: 31 | 32 | `openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout private.key -out certificate_pub.crt` 33 | 34 | ![Generate public certificate](Images/auth_jwtqs_00.png "Generate Public certificate") 35 | 36 | _**Windows:**_ 37 | 38 | 1. Download an OpenSSL client to generate public certificates; for example, you can try the [OpenSSL Windows client](https://bintray.com/vszakats/generic/download_file?file_path=openssl-1.1.1-win64-mingw.zip). 39 | 40 | 2. Extract the folder and copy it to the C:/libs/ location. 41 | 42 | 3. Open a command line window and execute the following commands: 43 | 44 | `set OPENSSL_CONF=C:/libs/openssl-1.1.1-win64-mingw/openssl.cnf` 45 | 46 | `cd C:/libs/openssl-1.1.1-win64-mingw/` 47 | 48 | `openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout private.key -out certificate_pub.crt` 49 | 50 | ![Generate public certificate windows](Images/auth_jwtqs_000.png "Generate Public certificate windows") 51 | 52 | Once you’ve complete the steps for your chosen platform, continue in the Adobe Developer Console: 53 | 54 | 6. Upload the public certificate (certificate_pub.crt) as a part of creating the integration. 55 | ![Upload public certificate](Images/auth_jwtqs_03.png "Upload public certificate") 56 | 57 | 7. Your integration should now be created with the appropriate public certificate and claims. 58 | ![Integration created](Images/auth_jwtqs_04.png "Integration created") 59 | 60 | 8. Go to the JWT tab and paste in you private key to generate a JWT. 61 | ![JWT tab](Images/auth_jwtqs_05.png "JWT tab") 62 | 63 | 9. Copy the “Sample CURL Command” to get your first access token. 64 | ![Get access token](Images/auth_jwtqs_06.png "Get access token") 65 | 66 | 10. Open Postman, then click Import > Paste Raw Text and paste the copied curl command. 67 | ![Postman import](Images/auth_jwtqs_07.png "Postman import") 68 | 69 | 11. Click Send. 70 | ![Postman send](Images/auth_jwtqs_08.png "Postman send") 71 | 72 | The example curl sends a POST request to [https://ims-na1.adobelogin.com/ims/exchange/jwt](https://ims-na1.adobelogin.com/ims/exchange/jwt) with the following parameters. 73 | 74 | | Parameter | Description| 75 | |---|---| 76 | | `client_id` | The API key generated for your integration. Find this on the I/O Console for your integration. | 77 | | `client_secret` | The client secret generated for your integration. Find this on the I/O Console for your integration. | 78 | | `jwt_token` | A base-64 encoded JSON Web Token that encapsulates the identity of your integration, signed with a private key that corresponds to a public key certificate attached to the integration. Generate this on the I/O Console in the JWT Tab for your integration. Note that this token has the expiration time parameter `exp` set to 24 hours from when the token is generated. | 79 | 80 | You now have your access token. Look up documentation for the specific API service for which you’re hitting authenticated endpoints to find what other parameters are expected. Most of them need an `x-api-key`, which will be the same as your `client_id`. 81 | -------------------------------------------------------------------------------- /OAuth/samples/adobe-auth-node/readme.md: -------------------------------------------------------------------------------- 1 | # OAuth 2.0 Example: Node.js 2 | 3 | This sample app will show you how to implement Adobe OAuth 2.0 using Node.js. 4 | 5 | After setting up the sample, you will have a Node.js app that: 6 | 7 | 1. Runs on `https://localhost:8000` 8 | 2. Lets a user log in with their Adobe ID 9 | 3. Prompts the user to authorize the app with requested scopes 10 | 4. Lets the user view their Adobe ID profile information 11 | 5. Lets the user log out 12 | 13 | 14 | 15 | 16 | 17 | ## Contents 18 | 19 | - [OAuth 2.0 Example: Node.js](#oauth-20-example-nodejs) 20 | - [Contents](#contents) 21 | - [Technology Used](#technology-used) 22 | - [Prerequisites](#prerequisites) 23 | - [Configuration](#configuration) 24 | - [Install Node.js packages](#install-nodejs-packages) 25 | - [Store your Adobe API credentials as Environment Variables](#store-your-adobe-api-credentials-as-environment-variables) 26 | - [Create an OpenSSL cert for Local Development](#create-an-openssl-cert-for-local-development) 27 | - [Usage](#usage) 28 | - [Other Resources](#other-resources) 29 | 30 | 31 | 32 | ## Technology Used 33 | 34 | 1. Node.js and the `npm` package manager 35 | 1. `mkcert` SSL certificate installer/configuration 36 | 37 | ## Prerequisites 38 | 39 | This guide will assume that you have read the [Adobe OAuth 2.0 Guide for Web](../../OAuth.md). 40 | 41 | You must also have [a registered app on the Adobe Developer Console](../../../AuthenticationOverview/OAuthIntegration.md) with the following settings: 42 | 43 | 1. `Platform`: web 44 | 1. `Default redirect URI`: `https://localhost:8000/callback/` 45 | 1. `Redirect URI Pattern`: `https://localhost:8000/callback/` 46 | 47 | ## Configuration 48 | 49 | The following steps will help you get this sample up and running. 50 | 51 | ### Install Node.js packages 52 | 53 | The `package.json` file contains a list of dependencies. Run the following command from the top level directory of the app to install these dependencies: 54 | 55 | ``` 56 | $ npm install 57 | ``` 58 | 59 | ### Store your Adobe API credentials as Environment Variables 60 | 61 | Set up a `.env` file to store the API Key and Secret. Create it on the same level as the `package.json` file -- you should see that it is already included in the `.gitignore` file to ensure that our source control history won't contain references to your secrets. 62 | 63 | ``` 64 | API_KEY=###################### 65 | API_SECRET=################### 66 | ``` 67 | 68 | To use your secrets, just insert this line in your code. 69 | ``` 70 | require('dotenv').config(); 71 | ``` 72 | This will require the `dotenv` package and execute the `config` function, which reads the `.env` file and sets your environment variables, which you can now access using `process.env.API_KEY` and `process.env.API_SECRET`. 73 | 74 | You can get your Adobe API Key and Secret from your registered app page on the [Adobe Developer Console](../../web-oauth2.0-guide.md#register-your-application-and-enable-apis). 75 | 76 | 77 | ### Create an OpenSSL cert for Local Development 78 | 79 | Adobe OAuth 2.0 requires SSL, so you will need to create a self-signed cert using the OpenSSL CLI. On production servers this is not an issue, but users running local development servers will have to do this next step. 80 | 81 | Make sure you have command-line tool `mkcert` installed on your machine first (for Mac users: recommend using `brew install`). 82 | 83 | Once it is installed, in the same folder as your entrypoint file (`index.js` in our case), run the line `mkcert localhost`. This will generate key and certificate files. Now we can use the key and certificate to spin up a HTTPS server like so: 84 | 85 | ``` 86 | /* Set up a HTTPS server with the signed certification */ 87 | var httpsServer = https.createServer({ 88 | key: fs.readFileSync(path.join(__dirname,'./localhost-key.pem')), 89 | cert: fs.readFileSync(path.join(__dirname, './localhost.pem')) 90 | }, app).listen(port, hostname, (err) => { 91 | if (err) console.log(`Error: ${err}`); 92 | console.log(`listening on port ${port}!`); 93 | }); 94 | ``` 95 | 96 | ## Usage 97 | 98 | After completing the configuration steps, start the server: 99 | 100 | ``` 101 | $ npm start 102 | ``` 103 | 104 | To access the app, go to `https://localhost:8000`. Try logging in with your Adobe ID first then click "Get Profile" to view relevant user info. You can also log out and the session will destroy user credentials. 105 | 106 | ## Other Resources 107 | 108 | - [Adobe OAuth 2.0 Guide for Web](../../web-oauth2.0-guide.md) 109 | -------------------------------------------------------------------------------- /JWT/Scopes.md: -------------------------------------------------------------------------------- 1 | # JWT Metascopes 2 | 3 | JSON Web Token (JWT) metascopes govern the access and privileges for service accounts. As an application developer, you will choose the set of scopes to access certain resources by specifying the scopes as part of the encoding claims for your JWTs. 4 | 5 | 6 | 7 | 8 | 9 | 10 | ## Contents 11 | 12 | - [Adobe I/O](#adobe-io) 13 | - [Creative Cloud](#creative-cloud) 14 | - [Document Cloud](#document-cloud) 15 | - [Experience Cloud](#experience-cloud) 16 | - [GDPR](#gdpr) 17 | - [Sensei](#sensei) 18 | - [User Management](#user-management) 19 | - [Other](#other) 20 | 21 | 22 | ## Adobe I/O 23 | 24 | Metascopes for Adobe I/O Service Account APIs 25 | 26 | | APIs | Metascopes | 27 | | -------------- | ----------------------------------------------------- | 28 | | I/O Events | `https://ims-na1.adobelogin.com/s/event_receiver_api` | 29 | | I/O Management | `https://ims-na1.adobelogin.com/s/ent_adobeio_sdk` | 30 | 31 | ## Creative Cloud 32 | 33 | Metacopes for Creative Cloud Service Account APIs 34 | 35 | | APIs | Metascopes | 36 | | -------------------------- | ------------------------------------------------------ | 37 | | Adobe Stock | `https://ims-na1.adobelogin.com/s/ent_stocksearch_sdk` | 38 | | Dimension (default) | `https://ims-na1.adobelogin.com/s/ent_default_sdk` | 39 | | Dimension (CCE-AS version) | `https://ims-na1.adobelogin.com/s/ent_ccas_sdk` | 40 | | Photoshop (default) | `https://ims-na1.adobelogin.com/s/ent_default_sdk` | 41 | | Photoshop (CCE-AS version) | `https://ims-na1.adobelogin.com/s/ent_ccas_sdk` | 42 | | Lightroom (default) | `https://ims-na1.adobelogin.com/s/ent_default_sdk` | 43 | | Lightroom (CCE-AS version) | `https://ims-na1.adobelogin.com/s/ent_ccas_sdk` | 44 | 45 | ## Document Cloud 46 | 47 | Metascopes for Document Cloud Service Account APIs 48 | 49 | | APIs | Metascopes | 50 | | ------------ | -------------------------------------------------------- | 51 | | PDF Services | `https://ims-na1.adobelogin.com/s/ent_documentcloud_sdk` | 52 | 53 | ## Experience Cloud 54 | 55 | Metascopes for Experience Cloud Service Account APIs 56 | 57 | | APIs | Metascopes | 58 | | ------------------------------------------------ | ---------------------------------------------------------------------- | 59 | | Adobe Analytics | `https://ims-na1.adobelogin.com/s/ent_analytics_bulk_ingest_sdk` | 60 | | Experience Platform | `https://ims-na1.adobelogin.com/s/ent_dataservices_sdk` | 61 | | Campaign | `https://ims-na1.adobelogin.com/s/ent_campaign_sdk` | 62 | | Target | `https://ims-na1.adobelogin.com/s/ent_marketing_sdk` | 63 | | Experience Platform Launch (Admin) | `https://ims-na1.adobelogin.com/s/ent_reactor_admin_sdk` | 64 | | Experience Platform Launch (IT Admin) | `https://ims-na1.adobelogin.com/s/ent_reactor_it_admin_sdk` | 65 | | Experience Platform Launch (Developer) | `https://ims-na1.adobelogin.com/s/ent_reactor_developer_sdk` | 66 | | Experience Platform Launch (Approver) | `https://ims-na1.adobelogin.com/s/ent_reactor_approver_sdk` | 67 | | Experience Platform Launch (Publisher) | `https://ims-na1.adobelogin.com/s/ent_reactor_publisher_sdk` | 68 | | Experience Platform Launch (Extension developer) | `https://ims-na1.adobelogin.com/s/ent_reactor_extension_developer_sdk` | 69 | 70 | ## GDPR 71 | 72 | Metascopes for GDPR Service Account APIs 73 | 74 | | APIs | Metascopes | 75 | | ---- | ----------------------------------------------- | 76 | | GDPR | `https://ims-na1.adobelogin.com/s/ent_gdpr_sdk` | 77 | 78 | ## Sensei 79 | 80 | Metascopes for Sensei Service Account APIs 81 | 82 | | APIs | Metascopes | 83 | | ------------------- | ------------------------------------------------------- | 84 | | Smart Content | `https://ims-na1.adobelogin.com/s/ent_smartcontent_sdk` | 85 | | Auto Crop, Auto Tag | `https://ims-na1.adobelogin.com/s/ent_sensei_image_sdk` | 86 | 87 | ## User Management 88 | 89 | Metascopes for User management Service Account APIs 90 | 91 | | APIs | Metascopes | 92 | | --------------- | ----------------------------------------------- | 93 | | User Management | `https://ims-na1.adobelogin.com/s/ent_user_sdk` | 94 | 95 | ## Other 96 | 97 | Metascopes for miscellaneous Service Account APIs 98 | 99 | | APIs | Metascopes | 100 | | ---------------- | ------------------------------------------------------- | 101 | | AEM Brand portal | `https://ims-na1.adobelogin.com/s/ent_brand_portal_sdk` | 102 | | Places | `https://ims-na1.adobelogin.com/s/ent_places_sdk` | 103 | | Cloud Manager | `https://ims-na1.adobelogin.com/s/ent_cloudmgr_sdk` | 104 | -------------------------------------------------------------------------------- /JWT/samples/adobe-jwt-java/src/main/java/io/adobe/solutions/IMSClient.java: -------------------------------------------------------------------------------- 1 | package io.adobe.solutions; 2 | 3 | import static java.lang.Boolean.TRUE; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.DataOutputStream; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.io.InputStreamReader; 10 | import java.net.URL; 11 | import java.nio.file.Files; 12 | import java.nio.file.Paths; 13 | import java.security.KeyFactory; 14 | import java.security.NoSuchAlgorithmException; 15 | import java.security.interfaces.RSAPrivateKey; 16 | import java.security.spec.InvalidKeySpecException; 17 | import java.security.spec.KeySpec; 18 | import java.security.spec.PKCS8EncodedKeySpec; 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | import java.util.Properties; 22 | 23 | import javax.net.ssl.HttpsURLConnection; 24 | 25 | import org.json.JSONObject; 26 | 27 | import io.jsonwebtoken.Jwts; 28 | import io.jsonwebtoken.SignatureAlgorithm; 29 | 30 | public class IMSClient { 31 | public static void main(String[] args) throws IOException { 32 | Properties prop = new Properties(); 33 | 34 | InputStream input = IMSClient.class.getClassLoader().getResourceAsStream("config.properties"); 35 | // load a properties file 36 | prop.load(input); 37 | 38 | try { 39 | String jwtToken = getJWTToken(prop); 40 | if(jwtToken != null && jwtToken != "") { 41 | System.out.println("JWT Token: " + jwtToken); 42 | String accessToken = getAccessToken(prop, jwtToken); 43 | System.out.println("Access Token: " + accessToken); 44 | } 45 | } catch(Exception e) { 46 | System.out.println("Error Occurred: " + e.getMessage()); 47 | } 48 | } 49 | 50 | public static String getJWTToken(Properties prop) 51 | throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { 52 | // Load relevant properties from prop file 53 | String orgId = prop.getProperty("orgId"); 54 | String technicalAccountId = prop.getProperty("technicalAccountId"); 55 | String apiKey = prop.getProperty("apiKey"); 56 | String keyPath = prop.getProperty("key_path"); 57 | String imsHost = prop.getProperty("imsHost"); 58 | // Expiration time in seconds 59 | Long expirationTime = System.currentTimeMillis() / 1000 + 86400L; 60 | // Metascopes associated to key 61 | String metascopes[] = prop.getProperty("metascopes").split(","); 62 | 63 | // # create the certificate and private key using openssl 64 | // $ openssl req -nodes -text -x509 -newkey rsa:2048 -keyout secret.pem -out 65 | // certificate.pem -days 356 66 | // 67 | // Upload the certificate.pem in Adobe IO Console-> Your Integration-> Public 68 | // keys 69 | // 70 | // # convert private key to DER format 71 | // $ openssl pkcs8 -topk8 -inform PEM -outform DER -in secret.pem -nocrypt > 72 | // secret.key 73 | 74 | // Secret key as byte array. Secret key file should be in DER encoded format. 75 | byte[] privateKeyFileContent = Files.readAllBytes(Paths.get(keyPath)); 76 | 77 | // Read the private key 78 | KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 79 | KeySpec ks = new PKCS8EncodedKeySpec(privateKeyFileContent); 80 | RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(ks); 81 | 82 | // Create JWT payload 83 | Map jwtClaims = new HashMap<>(); 84 | jwtClaims.put("iss", orgId); 85 | jwtClaims.put("sub", technicalAccountId); 86 | jwtClaims.put("exp", expirationTime); 87 | jwtClaims.put("aud", "https://" + imsHost + "/c/" + apiKey); 88 | for(String metascope : metascopes) { 89 | jwtClaims.put("https://" + imsHost + "/s/" + metascope, TRUE); 90 | } 91 | 92 | SignatureAlgorithm sa = SignatureAlgorithm.RS256; 93 | // Create the final JWT token 94 | String jwtToken = Jwts.builder().setClaims(jwtClaims).signWith(sa, privateKey).compact(); 95 | 96 | return jwtToken; 97 | } 98 | 99 | public static String getAccessToken(Properties prop, String jwtToken) throws IOException { 100 | // Load relevant properties from prop file 101 | String accessToken = ""; 102 | String imsExchange = prop.getProperty("imsExchange"); 103 | String apiKey = prop.getProperty("apiKey"); 104 | String secret = prop.getProperty("secret"); 105 | 106 | URL obj = new URL(imsExchange); 107 | 108 | HttpsURLConnection con = (HttpsURLConnection) obj.openConnection(); 109 | 110 | // add request header 111 | con.setRequestMethod("POST"); 112 | 113 | // Add parameters to request 114 | String urlParameters = "client_id=" + apiKey + "&client_secret=" + secret + "&jwt_token=" + jwtToken; 115 | 116 | // Send post request 117 | con.setDoOutput(true); 118 | DataOutputStream wr = new DataOutputStream(con.getOutputStream()); 119 | wr.writeBytes(urlParameters); 120 | wr.flush(); 121 | wr.close(); 122 | 123 | int responseCode = con.getResponseCode(); 124 | System.out.println("Sending 'POST' request to URL: " + imsExchange); 125 | System.out.println("Post parameters: " + urlParameters); 126 | System.out.println("Response Code: " + responseCode); 127 | 128 | boolean responseError = false; 129 | InputStream is; 130 | if(responseCode < HttpsURLConnection.HTTP_BAD_REQUEST) { 131 | is = con.getInputStream(); 132 | } else { 133 | /* error from server */ 134 | is = con.getErrorStream(); 135 | responseError = true; 136 | } 137 | 138 | BufferedReader in = new BufferedReader(new InputStreamReader(is)); 139 | String inputLine; 140 | StringBuilder response = new StringBuilder(); 141 | 142 | while((inputLine = in.readLine()) != null) { 143 | response.append(inputLine); 144 | } 145 | in.close(); 146 | 147 | if(responseError) { 148 | System.out.println(response.toString()); 149 | } 150 | 151 | JSONObject jObject = new JSONObject(response.toString()); 152 | accessToken = jObject.getString("access_token"); 153 | 154 | return accessToken; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /JWT/samples/adobe-jwt-php/AccessTokenProvider.php: -------------------------------------------------------------------------------- 1 | 'JWT', 'alg' => self::SIGN_ALGORITHM]; 34 | 35 | $headerJson = json_encode($header); 36 | $segments[] = $this->urlSafeB64Encode($headerJson); 37 | 38 | $payloadJson = json_encode($payload); 39 | echo "Paylod JSON:\n" . $payloadJson . "\n\n"; 40 | $segments[] = $this->urlSafeB64Encode($payloadJson); 41 | 42 | //now going to use openssl_sign() 43 | $result = openssl_sign(implode('.', $segments), 44 | $signature, 45 | $key, 46 | 'sha256'); 47 | if (false === $result) { 48 | throw new \RuntimeException('Failed to encrypt value. ' . implode("\n", $this->getSslErrors())); 49 | } 50 | $segments[] = $this->urlSafeB64Encode($signature); 51 | 52 | return implode('.', $segments); //PACK THE ARRAY CONTAINING JWT 53 | 54 | } 55 | 56 | /** 57 | * Encode a string with URL-safe Base64. 58 | * 59 | * @param string $input The string you want encoded 60 | * 61 | * @return string 62 | */ 63 | private function urlSafeB64Encode(string $input): string 64 | { 65 | return str_replace('=', '', strtr(base64_encode($input), '+/', '-_')); 66 | } 67 | 68 | 69 | /** 70 | * Builds request JWT. 71 | * 72 | * @param string $formattableTimeString 73 | * @param string $issuer 74 | * @param string $subject 75 | * @param string $audience 76 | * @param string $metascopes 77 | * @return string[] 78 | */ 79 | public function buildJWTPayload($formattableTimeString, $issuer, $subject, $audience, $metascopes) 80 | { 81 | 82 | $data = [ 83 | "exp" => strtotime($formattableTimeString), 84 | "iss" => $issuer, 85 | "sub" => $subject, 86 | "aud" => $audience 87 | ]; 88 | 89 | if (is_array($metascopes)) { 90 | foreach ($metascopes as &$aMetascope) { 91 | $data[METASCOPE_ENDPOINT_PREFIX . $aMetascope] = true; 92 | } 93 | } else { 94 | // single metascope 95 | $data[METASCOPE_ENDPOINT_PREFIX . $metascopes] = true; 96 | } 97 | 98 | return $data; 99 | } 100 | 101 | } 102 | 103 | 104 | /** Authenticates with Adobe IO - returns Auth Response 105 | * @param $jwt 106 | * @param $client_id 107 | * @param $client_secret 108 | * @return mixed | 109 | */ 110 | function doAdobeIOAuth($jwt, $client_id, $client_secret) 111 | { 112 | $curl = curl_init(); 113 | curl_setopt($curl, CURLOPT_POST, 1); 114 | curl_setopt($curl, CURLOPT_POSTFIELDS, array( 115 | "client_id" => $client_id, 116 | "client_secret" => $client_secret, 117 | "jwt_token" => $jwt, 118 | 119 | )); 120 | curl_setopt($curl, CURLOPT_URL, AUTH_ENDPOINT); 121 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 122 | 123 | $result = curl_exec($curl); 124 | 125 | curl_close($curl); 126 | 127 | return $result; 128 | } 129 | 130 | /** psvm - example implementation 131 | * Usage: 132 | * AccessTokenProvider.php -i -s -k -u -b -c -e " 133 | */ 134 | function psvm() 135 | { 136 | 137 | $cl_options = "" 138 | . "i:" // Client Id 139 | . "s:" // Client Secret 140 | . "k:" // Key File path 141 | . "u:" // Issuer 142 | . "b:" // Subject 143 | . "c:" // metascopes 144 | . "e::"; // expires 145 | 146 | $show_usage = false; 147 | $cmdLineOpts = getopt($cl_options); 148 | 149 | if (isset($cmdLineOpts["i"])) { 150 | $client_id = $cmdLineOpts["i"]; 151 | if (isset($cmdLineOpts["s"])) { 152 | $client_secret = $cmdLineOpts["s"]; 153 | if (isset($cmdLineOpts["k"])) { 154 | $key_file = $cmdLineOpts["k"]; 155 | echo "Key file is " . $key_file . "\n"; 156 | if (is_file($key_file) && is_readable($key_file)) { 157 | $fHandle = fopen($key_file, "r") or die("Unable to read the key file " . $key_file . "\n"); 158 | $private_key = fread($fHandle, filesize($key_file)) or die("Unable to read the key file " . $key_file . "\n"); 159 | fclose($fHandle); 160 | if (isset($cmdLineOpts["u"])) { //Checking issuer 161 | $issuer = $cmdLineOpts["u"]; 162 | if (isset($cmdLineOpts["b"])) { //checking subject 163 | $subject = $cmdLineOpts["b"]; 164 | $audience = AUD_ENDPOINT_PREFIX . $client_id; //preparing audience 165 | if (isset($cmdLineOpts["c"])) { //checking metascopes 166 | 167 | $metascopes = preg_split("/,/", $cmdLineOpts["c"]); 168 | 169 | if (isset($cmdLineOpts["e"])) { 170 | $exp_time = $cmdLineOpts["e"]; 171 | } else { 172 | echo "exp_time not provided assuming 1 day\n"; 173 | $exp_time = '1 Day'; 174 | } 175 | 176 | $jwtInstance = new JWTProvider(); 177 | 178 | $payload = $jwtInstance->buildJWTPayload($exp_time, 179 | $issuer, 180 | $subject, 181 | $audience, 182 | $metascopes); 183 | 184 | $jwt = $jwtInstance->encode($payload, $private_key); 185 | 186 | echo "JWT Prepared:" . $jwt . "\n\n"; 187 | 188 | $result = doAdobeIOAuth($jwt, $client_id, $client_secret); 189 | 190 | echo "Result of Auth:\n\n" . $result . "\n"; 191 | } else { 192 | echo "Metascopes not provided\n"; 193 | $show_usage = true; 194 | } 195 | } else { 196 | echo "Subject not provided\n"; 197 | $show_usage = true; 198 | 199 | } 200 | } else { 201 | echo "Issuer not provided\n"; 202 | $show_usage = true; 203 | 204 | } 205 | } else { 206 | echo "Unable to read the key file " . $key_file . '\n'; 207 | } 208 | } else { 209 | echo "Key file location not provided\n"; 210 | $show_usage = true; 211 | } 212 | } else { 213 | echo "Client-secret not provided\n"; 214 | $show_usage = true; 215 | } 216 | } else { 217 | echo "Client ID not provided\n"; 218 | $show_usage = true; 219 | } 220 | 221 | if ($show_usage) { 222 | echo "Usage:\n AccessTokenProvider.php -i -s -k -u -b -a -c -e "; 223 | } 224 | } 225 | 226 | psvm(); 227 | exit(1); -------------------------------------------------------------------------------- /OAuth/OAuth.md: -------------------------------------------------------------------------------- 1 | # OAuth 2.0 Authentication and Authorization 2 | 3 | Adobe Cloud Platform APIs use the OAuth 2.0 protocol for authentication and authorization. Using Adobe OAuth 2.0, you can generate an access token using the [OAuth Integration](../AuthenticationOverview/OAuthIntegration.md) created in [Adobe Developer Console](https://www.adobe.io/console) which is used to make API calls from your web server or browser-based apps. 4 | 5 | ## Authentication Workflow 6 | 7 | - [Authorization](#authorization) 8 | - [Authentication](#authentication) 9 | 10 | The basic web OAuth 2.0 workflow will look like: 11 | 12 | 1. Your application _redirects_ the user to Adobe along with the list of requested permissions. 13 | 2. Adobe prompts the user with a login screen and informs the user of the requested permissions. 14 | 3. The user decides whether to grant the permissions. 15 | 4. Adobe sends a _callback_ to your application to notify whether the user granted the permissions. 16 | 5. After permissions are granted, your application retrieves tokens required to make API requests on behalf of the user. 17 | 18 | The process of providing secure access to protected resources has two stages, _authorization_ and _authentication_. It is important to understand that they are separate concepts: 19 | 20 | - **Authorization** is the process of granting permission to a user to access a protected resource. Because authentication is usually a prerequisite for granting access, these two terms often occur together. 21 | - **Authentication** is the process of determining that a user is who she claims to be. Authentication can be checked by Adobe’s own identity provider, the Identity Management Services (IMS). 22 | 23 | 24 | ### Authorization 25 | The first step is to request the authorization token. This request sets the access scope and asks the user to grant permission to your application. To start this workflow, redirect the user to the Adobe’s authorization endpoint: 26 | 27 | `https://ims-na1.adobelogin.com/ims/authorize` 28 | 29 | Include the following parameters: 30 | 31 | Parameter | Description 32 | ---- | ---- 33 | `client_id` | The Client ID obtained from the [Adobe Developer Console](https://www.adobe.io/console). 34 | `redirect_uri` | Optional. The URI to which the user agent is redirected once the authorization completes. Note that this URI must be HTTPS. The pattern is validated against the list of valid redirect URIs configured for your client. If the redirect URI is not provided with the request, it will consider the Default Redirect URI in Adobe Developer Console. 35 | `scope` | The scope of the access request, expressed as a list of comma-delimited, case-sensitive strings. See the [Scope Reference](Scopes.md) for more information. 36 | `response_type` | The default response type for the Authorization code flow is `code`. 37 | `locale` | Optional. The locale code for the authentication UI. Default is `en_US`. 38 | `state` | Optional. Client-defined state data that is replayed back to the client. It must not be longer than 255 characters. The value should be sent in JSON format: for example, `state={"st":`_`some_alphanumeric_value`_`}`. This parameter should be used to prevent CSRF ([Cross-Site Request Forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery 'Cross-Site Request Forgery')). 39 | 40 | > **Note:** Adobe OAuth does not support the practice of passing base64-encoded `client_id` and `client_secret` parameters using the HTTP BASIC authorization header. 41 | 42 | Example URL (code response type): 43 | 44 | ``` 45 | https://ims-na1.adobelogin.com/ims/authorize 46 | ?client_id= 47 | &redirect_uri=https://www.myapp.com/OAuth/callback 48 | &scope=openid 49 | &response_type=code 50 | ``` 51 | 52 | ### Prompting the user for consent 53 | 54 | Once the request from the previous step is sent, Adobe will redirect the user to the Adobe ID sign-in page. After sign-in, the user will see a consent window showing the name of your application and the information that your application is requesting permission to access with the user’s credentials: 55 | 56 | ![oauth-5](../Images/oauth-5.png) ![oauth-6](../Images/oauth-6.png) 57 | 58 | The user can either allow or refuse access. 59 | 60 | ### Handling the callback 61 | 62 | Adobe’s OAuth 2.0 server will respond to your application’s access request by using the redirect URI specified in the request. If the user has signed in successfully and granted permissions, the OAuth 2.0 server will respond with an authorization code in the query string. If the user has not approved the request, the OAuth 2.0 server will send an error message. 63 | 64 | Example Authorization grant type response (`code` response type): 65 | `https://www.myapp.com/OAuth/callback?code=eyJ4NXUiOiJpbXNfbmExLWtleS...` 66 | 67 | ### Authentication 68 | 69 | After receiving the authorization code, send a POST request to the token endpoint: 70 | `https://ims-na1.adobelogin.com/ims/token/` 71 | 72 | Include the following parameters: 73 | 74 | Parameters | Description 75 | ---- | ---- 76 | `code` | The base64-encoded `authorization_code` returned from the `/ims/authorize/` request in callback. 77 | `grant_type` | The constant value `authorization_code`. 78 | `client_id` | The Client ID obtained from the [Adobe Developer Console](https://www.adobe.com/go/devs_console_ui/). 79 | `client_secret` | The Client Secret obtained from the [Adobe Developer Console](https://www.adobe.com/go/devs_console_ui/). 80 | 81 | > **Note:** Adobe OAuth does not support the practice of passing base64-encoded `client_id` and `client_secret` parameters using the HTTP BASIC authorization header. 82 | Example request: 83 | 84 | ```curl 85 | curl -X POST \ 86 | https://ims-na1.adobelogin.com/ims/token \ 87 | -H 'Content-Type: application/x-www-form-urlencoded' \ 88 | -H 'cache-control: no-cache' \ 89 | -d 'code=eyJ4NXUiOiJpbXNfbmExLWt.......&grant_type=authorization_code&client_id=0b623b30......&client_secret=a9a10933-95d9-......' 90 | ``` 91 | 92 | Example response: 93 | 94 | ``` 95 | HTTP/1.1 200 OK 96 | Content-Type: application/json;charset=UTF-8 97 | 98 | { 99 | "access_token": "eyJ4NXU...", 100 | "refresh_token": "eyJ4NXU...", 101 | "sub": "5BEB2BB...@AdobeID", 102 | "address": { 103 | "country": "US" 104 | }, 105 | "email_verified": "true", 106 | "name": "USERNAME", 107 | "token_type": "bearer", 108 | "given_name": "USERNAME", 109 | "expires_in": 86399985, 110 | "family_name": "USERNAME", 111 | "email": "USERNAME@example.com" 112 | } 113 | ``` 114 | 115 | Similar to above, note that in addition to the `access_token` and `refresh_token`, the response also includes a JSON array of profile data for which your `client_id` is authorized and which is appropriate for the scope that you requested. 116 | 117 | ### Exchanging a refresh token for an access token 118 | 119 | The default expiry of access tokens is 24 hours. You can refresh an access token without prompting the user for permission again even if a user is not present. The refresh token, by default, expires in 2 weeks. 120 | 121 | > **Note:** Not all product APIs support the `refresh_token` grant type. You may not be able to get a valid response for such integrations. Please try creating a **Service Account Integration** for such APIs to create a service-service integration. 122 | You can send a POST request to the token endpoint: 123 | 124 | `https://ims-na1.adobelogin.com/ims/token/` 125 | 126 | Include the following parameters: 127 | 128 | | Parameters | Description | 129 | | ------------- |:--------------------------------------------------------| 130 | | `refresh_token` |The base64-encoded refresh token received in the response to the initial request for an access token.| 131 | | `grant_type` |The constant value `refresh_token`.| 132 | | `client_id` |The Client ID obtained from the [Adobe Developer Console](https://www.adobe.com/go/devs_console_ui/integrations).| 133 | | `client_secret` |The Client Secret obtained from the [Adobe Developer Console](https://www.adobe.com/go/devs_console_ui/integrations).| 134 | 135 | > **Note:** Adobe OAuth does not support the practice of passing base64-encoded `client_id` and `client_secret` parameters using the HTTP BASIC authorization header. 136 | 137 | Example request: 138 | 139 | ``` 140 | POST /ims/token HTTP/1.1 141 | Host: ims-na1.adobelogin.com 142 | 143 | Content-Type: application/x-www-form-urlencoded 144 | grant_type=refresh_token 145 | &client_id= 146 | &client_secret= 147 | &refresh_token= 148 | ``` 149 | 150 | Example response: 151 | 152 | ``` 153 | HTTP/1.1 200 OK 154 | Content-Type: application/json;charset=UTF-8 155 | 156 | { 157 | "access_token": "eyJ4NXU...", 158 | "refresh_token": "eyJ4NXU...", 159 | "sub": "5BEB2BB...@AdobeID", 160 | "address": { 161 | "country": "US" 162 | }, 163 | "email_verified": "true", 164 | "name": "USERNAME", 165 | "token_type": "bearer", 166 | "given_name": "USERNAME", 167 | "expires_in": 86399985, 168 | "family_name": "USERNAME", 169 | "email": "USERNAME@example.com" 170 | } 171 | ``` 172 | 173 | Similar to above, note that in addition to the `access_token` and `refresh_token`, the response also includes a JSON array of profile data for which your `client_id` is authorized, and which is appropriate for the scope that you requested. 174 | 175 | ### Revoking authorization for end user 176 | 177 | Users can revoke access to your application themselves by visiting the [Connected Applications](https://accounts.adobe.com/security/connected-applications#) page. The next time the user launches your application, the authorization workflow will start from the beginning. 178 | 179 | 180 | -------------------------------------------------------------------------------- /JWT/JWT.md: -------------------------------------------------------------------------------- 1 | # JWT (Service Account) Authentication 2 | 3 | To establish a secure service-to-service Adobe I/O API session, you must create a JSON Web Token (JWT) that encapsulates the identity of your integration, and then exchange it for an access token. Every request to an Adobe service must include the access token in the `Authorization` header, along with the API Key (Client ID) that was generated when you created the [Service Account Integration](../AuthenticationOverview/ServiceAccountIntegration.md) in the [Adobe Developer Console](https://www.adobe.com/go/devs_console_ui/). 4 | 5 | ## Authentication Workflow 6 | 7 | - [Creating a JSON Web Token](#creating-a-json-web-token) 8 | - [Exchanging JWT to retrieve an access token](#exchanging-jwt-to-retrieve-an-access-token) 9 | 10 | ## Creating a JSON Web Token 11 | 12 | A JSON Web Token for Service Account authentication requires a particular set of claims, and must be signed using a valid digital signing certificate. We recommend that you use one of the publicly available libraries or tools for building your JWT. Examples are provided for some popular languages. 13 | 14 | ### Required Claims for a Service Account JWT 15 | 16 | Your JWT must contain the following claims: 17 | 18 | | Claim | Description| 19 | |---|---| 20 | | exp | _Required_. The expiration parameter is a required parameter measuring the absolute time since 01/01/1970 GMT. You must ensure that the expiration time is later than the time of issue. After this time, the JWT is no longer valid. **Recommendation**: Have a very short lived token (a few minutes) - such that it expires soon after it has been exchanged for an IMS access token. Every time a new access token is required, one such JWT is signed and exchanged. This is secure approach. Longer lived tokens that are re-used to obtain access tokens as needed are not recommended. | 21 | | iss | _Required_. The issuer, your **Organization ID** from the Adobe Developer Console integration, in the format `org_ident@AdobeOrg`. Identifies your organization that has been configured for access to the Adobe I/O API.| 22 | | sub | _Required_. The subject, your **Technical Account ID** from the Adobe Developer Console integration, in the format: `id@techacct.adobe.com`.| 23 | | aud | _Required_. The audience for the token, your **API Key** from the Adobe Developer Console integration, in the format: `https://ims-na1.adobelogin.com/c/api_key`.| 24 | | Metascopes | _Required_. The API-access claim configured for your organization: [JWT Metascopes](Scopes.md), in the format: `"https://ims-na1.adobelogin.com/s/meta_scope": true`| 25 | 26 | The following is a sample payload to be signed and encoded. 27 | 28 | ```json 29 | { 30 | "exp": 1550001438, 31 | "iss": "C74F69D7594880280.....@AdobeOrg", 32 | "sub": "6657031C5C095BB40A4.....@techacct.adobe.com", 33 | "https://ims-na1.adobelogin.com/s/ent_dataservices_sdk": true, 34 | "aud": "https://ims-na1.adobelogin.com/c/a64f5f10849a410a97ffdac8ae1....." 35 | } 36 | ``` 37 | 38 | ### Sign and Encode your JWT 39 | 40 | The JWT must be signed and base-64 encoded for inclusion in the access request. The JWT libraries provide functions to perform these tasks. 41 | 42 | - The token must be signed using the private key for a digital signing certificate that is associated with your API key. You can associate more than one certificate with an API key. If you do so, you can use the private key of any associated certificate to sign your JWT. For more information about private key/public certificate, see [Create a public key certificate](../AuthenticationOverview/ServiceAccountIntegration.md#step-2-create-a-public-key-certificate). 43 | 44 | **Algorithm**: **RS256** (RSA Signature with SHA-256) is an asymmetric algorithm, and it uses a public/private key pair: the identity provider has a private (secret) key used to generate the signature, and the consumer of the JWT (i.e. Adobe Developer Console) gets a public key to validate the signature. 45 | 46 | ### Using JWT Libraries and Creation Tools 47 | 48 | Most modern languages have JWT libraries available. We recommend you use one of these libraries (or other JWT-compatible libraries) before trying to hand-craft the JWT. 49 | 50 | Other JWT tools are publicly available, such as the [JWT.IO](https://jwt.io/), a handy web-based encoder/decoder for JWTs. 51 | 52 | Examples are provided for several popular languages. 53 | 54 | | Language | Library | 55 | | -------- | --------------------------- | 56 | | Java | `atlassian-jwt` `jsontoken` | 57 | | Node.js | `jsonwebtoken` | 58 | | Python | `pyjwt` | 59 | 60 | ### Additional JWT Libraries and Creation Tools 61 | 62 | The following JWT libraries are available, in addition to the Java, Node.js, and Python libraries for which we have provided examples. 63 | 64 | | Language | Library | 65 | | -------- | ----------------------------------- | 66 | | Ruby | `ruby-jwt` | 67 | | PHP | `firebase php-jwt` `luciferous jwt` | 68 | | .NET | `jwt` | 69 | | Haskell | `haskell-jwt` | 70 | 71 | ## Exchanging JWT to retrieve an access token 72 | 73 | To initiate an API session, use the JWT to obtain an access token from Adobe by making a POST request to Adobe Identity Management Service (IMS). 74 | 75 | - Send a POST request to: 76 | 77 | `https://ims-na1.adobelogin.com/ims/exchange/jwt` 78 | 79 | - The body of the request should contain URL-encoded parameters with your Client ID (API Key), Client Secret, and JWT: 80 | 81 | `client_id={api_key_value}&client_secret={client_secret_value}&jwt_token={base64_encoded_JWT}` 82 | 83 | ### Request parameters 84 | 85 | Pass URL-encoded parameters in the body of your POST request: 86 | 87 | | Parameter | Description | 88 | | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 89 | | client_id | The API key generated for your integration. | 90 | | client_secret | The client secret generated for your integration. | 91 | | jwt_token | A base-64 encoded JSON Web Token that encapsulates the identity of your integration, signed with a private key that corresponds to a public key certificate attached to the integration. | 92 | 93 | ### Responses 94 | 95 | When a request has been understood and at least partially completed, it returns with HTTP status 200. On success, the response contains a valid access token. Pass this token in the Authorization header in all subsequent requests to an Adobe service. 96 | 97 | A failed request can result in a response with an HTTP status of 400 or 401 and one of the following error messages in the response body: 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 133 | 134 | 135 | 136 | 137 | 138 | 139 |
ResponseDescription
400 invalid_clientIntegration does not exist. This applies both to the client_id parameter and the aud in the JWT. The client_id parameter and the aud field in the JWT do not match.
401 invalid_clientIntegration does not have the exchange_jwt scope. This indicates an improper client configuration. Contact the Adobe I/O team to resolve it. The client ID and client secret combination is invalid.
400 invalid_tokenJWT is missing or cannot be decoded. JWT has expired. In this case, the error_description contains more details. The exp or jti field of the JWT is not an integer.
400 invalid_signatureThe JWT signature does not match any certificates attached to the integration. The signature does not match the algorithm specified in the JWT header.
400 invalid_scopeIndicates a problem with the requested scope for the token. Specific scope problems can be: 126 |
    127 |
  • Metascopes in the JWT do not match metascopes in the binding.
  • 128 |
  • Metascopes in the JWT do not match target client scopes.
  • 129 |
  • Metascopes in the JWT contain a scope or scopes that do not exist.
  • 130 |
  • The JWT has no metascopes.
  • 131 |
132 |
400 bad_requestThe JWT payload can be decoded and decrypted, but its contents are incorrect. This can occur when values for fields such as sub, iss, exp, or jti are not in the proper format.
140 | 141 | ### Example 142 | 143 | ``` 144 | ========================= REQUEST ========================== 145 | POST https://ims-na1.adobelogin.com/ims/exchange/jwt 146 | -------------------------- body ---------------------------- 147 | client_id={myClientId}&client_secret={myClientSecret}&jwt_token={myJSONWebToken} 148 | ------------------------- headers -------------------------- 149 | Content-Type: application/x-www-form-urlencoded 150 | Cache-Control: no-cache 151 | ``` 152 | -------------------------------------------------------------------------------- /Backup/postmanQuickStart.md: -------------------------------------------------------------------------------- 1 | # JWT Authentication using Postman Environment Template and Collections 2 | 3 | ## What is JWT authentication? What are service account type integrations? 4 | JSON web tokens (JWT) are 5 | 6 | ## Why use Postman? 7 | 8 | 9 | ## Required setup 10 | 11 | ### Private/public key pair 12 | 13 | ### Service account type integration on I/O Console 14 | 15 | ### Postman installation 16 | 17 | ## Postman Collections 18 | 19 | 20 | ## Postman Environment Template 21 | 22 | 23 | ## Using [`jsrsasign`](https://github.com/kjur/jsrsasign) to create a JWT and request for an access token 24 | 25 | 26 | ## Using the access token to make authenticated calls 27 | 28 | 29 | ## Thanks 30 | Thanks to Klaasjan Tukker for the [original article](https://medium.com/adobetech/using-postman-for-jwt-authentication-on-adobe-i-o-7573428ffe7f). 31 | 32 | 33 | 34 | ## Introduction 35 | Working in the Adobe Cloud Platform — Data Services team, I am responsible for the API First strategy and availability of our APIs to Adobe and third party developers. We are using the Adobe I/O Gateway to provide developers access to these platform APIs. For authentication for third party developers, Adobe I/O is using an JWT workflow. Frequently I am testing APIs in [Postman] (https://www.getpostman.com/) and I was looking for a way to execute the full authentication flow, including the generation of JWT request, signed with SHA-256. The [Adobe Developer Console](https://www.adobe.com/go/devs_console_ui/) allows you to generate a new JWT token, but I was looking to do everything inside of Postman. Merely there was not a complete recipe available to do this, so I rolled up my sleeves, Googled and Stackoverflowed my way through the web to put together the approach documented in this article. This article was originally written for the [Adobe I/O Blog, hosted on Medium](https://medium.com/adobe-io/using-postman-for-jwt-authentication-on-adobe-i-o-7573428ffe7f). 36 | 37 | 38 | ## Setup I/O Integration 39 | To integrate with Adobe solutions, you can find all related information and documentation on the [adobe.io] (http://www.adobe.io) website. In this case we'll be using the service-to-service pattern (using JWT). This requires to setup a new integration using [Adobe Developer Console](https://www.adobe.com/go/devs_console_ui/). The steps to setup a new integration can be found [here](https://www.adobe.io/apis/cloudplatform/console/authentication/gettingstarted.html) or [here](https://www.adobe.io/apis/cloudplatform/dataservices/tutorials/alltutorials.html#!api-specification/markdown/narrative/tutorials/authenticate_to_acp_tutorial/authenticate_to_acp_tutorial.md). 40 | Once your integration is setup, you can use the details inside of Postman. In my case, I configured an integration to call the APIs for [Adobe Cloud Platform - Data Services](https://www.adobe.io/apis/cloudplatform/dataservices.html) and the screenshot with the results are below. I will use the details listed on this screen later. 41 | ![I/O integration details](https://github.com/ktukker/adobe.io-jwt-postman/raw/master/images/io_integration_details.png) 42 | 43 | ## Downloading and configuring Postman 44 | Postman is a very convenient tool to execute REST API calls, manage different libraries of pre-defined calls as well as different environments. I am working with various environments (internal development and staging environments, next to our production environment) and multiple customer account settings. 45 | 46 | * To get started, download Postman from the official [website] (https://www.getpostman.com/). 47 | * Download the Postman [collection](https://raw.githubusercontent.com/ktukker/adobe.io-jwt-postman/master/postman/collections/Adobe%20I-O.postman_collection.json) and [environment template](https://github.com/ktukker/adobe.io-jwt-postman/raw/master/postman/environments/JWT%20-%20Template.postman_environment.json) from the [Github repository](https://github.com/ktukker/adobe.io-jwt-postman). 48 | 49 | In Postman you can add the downloaded collection by clicking on the "Import" button on the top left and select the collection you want to import. 50 | ![Imported Postman Collection](https://github.com/ktukker/adobe.io-jwt-postman/raw/master/images/postman_collection.png) 51 | 52 | After importing the collection, import the pre-configured environment template. In the top right, click on the "Gear" icon and click on the "Import" button. Now you can select the downloaded environment template. 53 | ![Imported Postman Collection](https://github.com/ktukker/adobe.io-jwt-postman/raw/master/images/postman_environment_template.png) 54 | You are now ready to configure your environment based on the settings provided in IO Console. 55 | 56 | ## Setting up environments 57 | The Environments feature of Postman allows you to efficiently switch between multiple pre-configured environments. The [environment template](https://github.com/ktukker/adobe.io-jwt-postman/raw/master/postman/environments/JWT%20-%20Template.postman_environment.json) has pre-configured variable names that need to be populated with the correct values found in the I/O Console screen (see above). 58 | 59 | * Copy your values into the pre-configured template 60 | 61 | The value for `meta_scope` might be more challenging to find. This setting is different per solution / product that you integrate with. You can find this in the I/O Console for your created integration under the "JWT" tab. See highlighted element in the screenshot below. 62 | ![Imported Postman Collection](https://github.com/ktukker/adobe.io-jwt-postman/raw/master/images/where_to_find_the_metascope.png) 63 | In this case the `meta_scope` is `ent_dataservices_sdk`. If you have created an integration that is bound to multiple Adobe solutions, you will see multiple entries with different `meta_scope` values defined. In this case, add all the meta_scopes to the `meta_scope`, separated by a comma (`,`). For example `ent_dataservices_sdk,ent_reactor_sdk`. 64 | 65 | After configuring your template, it will look like this: 66 | ![Imported Postman Collection](https://github.com/ktukker/adobe.io-jwt-postman/raw/master/images/postman_environment_example.png) 67 | 68 | Note: The `secret` variable contains the full text of the private key that you generated for the selected integration. Copy and past it into the field including the header (`-----BEGIN RSA PRIVATE KEY------`) and footer. 69 | 70 | 71 | ## Bootstrapping the authentication process 72 | To be able to authenticate, you need to load the Crypto JavaScript library. This Postman script uses the ["RSA-Sign JavaScript Library"](https://github.com/kjur/jsrsasign). Due to limitations in the Postman sandbox, it needs to be loaded in a Global environment variable only once. 73 | 74 | * Click on "INIT: Load Crypto Library for RS256" in the left column of Postman (under the Adobe I/O Collection). 75 | * The pre-configured call will appear 76 | * Click "Send" 77 | 78 | This will load the JavaScript and store it in an internal variable for future use. When you shutdown Postman and start it up again, the script does not have to be run again as the internal variable still holds the value. 79 | ![Imported Postman Collection](https://github.com/ktukker/adobe.io-jwt-postman/raw/master/images/postman_load_crypto_library.png) 80 | 81 | ## Executing JWT authentication 82 | With the Crypto JavaScript Library in place, you can now execute the real JWT authentication flow. Make sure your environment is selected in the top right of the screen. 83 | 84 | * Click on "IMS: JWT Generate + Auth". This will generate the authentication code using the Crypto Library and call the Adobe Identity Server (IMS) to authenticate. 85 | 86 | The Postman call will generate a bearer token and automatically store it in the selected environment as `access_token`. 87 | 88 | As a next step, you can do a call to the Adobe IMS `/profile` endpoint. This will provide you additional details of the Integration you created and have authenticated with. 89 | 90 | In my case, I can now successfully call the Adobe Cloud Platform - Data Services APIs. For example access the Data Catalog to get a list of registered datasets. (Note this is only available if your Organization is provisioned for the "Data Services" solution). 91 | 92 | If you are using this in combination with another Adobe Solution that is using Service-to-Service authentication, make sure that you have configured the right `meta_scope` for that solution. 93 | 94 | ## How it works 95 | So, what is going on behind the scenes? This Postman script is using a JavaScript based Crypto library ([`jsrsasign`](http://kjur.github.io/jsrsasign/)) to use the "RS256" Encryption library. Normally, this library runs in the context of a browser sandbox, but in this case, we want it to use in Postman. I used the method provide [here](https://github.com/kjur/jsrsasign/issues/199) to load it into Postman. This is done using a 'Tests' script which is executed after the call has been completed: 96 | 97 | ``` 98 | postman.setGlobalVariable("jsrsasign-js", responseBody); 99 | ``` 100 | 101 | Once the library is ready for use, it can be used in the actual JWT generation process. In a 'pre-request Script', the JavaScript library is loaded using the `eval` command 102 | 103 | ``` 104 | var navigator = {}; //fake a navigator object for the lib 105 | var window = {}; //fake a window object for the lib 106 | eval(postman.getGlobalVariable("jsrsasign-js")); //import jsrsasign lib 107 | ``` 108 | 109 | Based on the environment variables for the current environment, the JWT payload is constructed: 110 | 111 | ``` 112 | var data = { 113 | "exp": Math.round(87000 + Date.now()/1000), 114 | "iss": postman.getEnvironmentVariable("IMSOrg"), 115 | "sub": postman.getEnvironmentVariable("techacct"), 116 | "aud": "https://ims-na1.adobelogin.com/c/"+postman.getEnvironmentVariable("clientID") 117 | }; 118 | 119 | var meta_scope = postman.getEnvironmentVariable("IMS")+"/s/"+ 120 | postman.getEnvironmentVariable("meta_scope"); 121 | data[meta_scope] = true; 122 | ``` 123 | 124 | This payload needs to be signed using the crypto library and the private key that is stored in the environment variable. The actual encryption code was conveniently published on the [jsrsasign wiki] (https://github.com/kjur/jsrsasign/wiki/Tutorial-for-JWT-generation). 125 | 126 | ``` 127 | var secret = postman.getEnvironmentVariable("secret"); 128 | 129 | var sHeader = JSON.stringify(header); 130 | var sPayload = JSON.stringify(data); 131 | var sJWT = KJUR.jws.JWS.sign("RS256", sHeader, sPayload, secret); 132 | 133 | postman.setEnvironmentVariable("jwt_token", sJWT); 134 | ``` 135 | 136 | The resulting token is stored in the environment again and is used in the call to the authentication server (IMS). When the call returns, a 'Test' script is parsing the response and stores the `bearer` token in the environment for use in subsequent calls. 137 | 138 | ``` 139 | var data = JSON.parse(responseBody); 140 | postman.setEnvironmentVariable("access_token", data.access_token); 141 | ``` 142 | 143 | This ```access_token``` is now used in REST calls to APIs exposed through the Adobe I/O Gateway and included in the ```Authorization``` header. 144 | 145 | 146 | ## Tips 147 | In this article, you have been working with JWT (JSON Web Tokens). A token might seems like a random string, but some very valuable information is stored in them. Using the website [jwt.io](https://jwt.io/) you can decipher JWT tokens. I am using this regularly to inspect tokens for debugging purposes. 148 | 149 | Example output of a generated JWT token (payload), which shows the content that was generated as part of the Postman script: 150 | 151 | ``` 152 | { 153 | "exp": 1525109214, 154 | "iss": "@AdobeOrg", 155 | "sub": "@techacct.adobe.com", 156 | "aud": "https://ims-na1.adobelogin.com/c/", 157 | "https://ims-na1.adobelogin.com/s/ent_dataservices_sdk": true 158 | } 159 | ``` 160 | 161 | You can do the same for an `access_token` that was returned after the JWT authentication flow. 162 | 163 | ``` 164 | Left as an exersize to the reader 165 | ``` 166 | 167 | ## Conclusion 168 | I hope you enjoyed this article and will be using Postman a lot for JWT based integration with Adobe I/O. With this script, you won't be needed a separate command line utility to generate and encrypt your JWT token or go to the Adobe Developer Console to generate one every time you need one. -------------------------------------------------------------------------------- /Backup/OAuth2.0Endpoints/web-oauth2.0-guide.md: -------------------------------------------------------------------------------- 1 | # OAuth 2.0 Guide for Web 2 | 3 | Adobe Cloud Platform APIs use the OAuth 2.0 protocol for authentication and authorization. Using Adobe OAuth 2.0, you can generate an access token which is used to make API calls from your web server or browser-based apps. 4 | 5 | The basic Web OAuth 2.0 workflow will look like: 6 | 7 | 1. Your application redirects the user to Adobe along with the list of requested permissions 8 | 1. Adobe prompts the user with a login screen and informs the user of the requested permissions 9 | 1. The user decides whether to grant the permissions 10 | 1. Adobe sends a callback to your application to notify whether the user granted the permissions 11 | 1. After permissions are granted, your application retrieves tokens required to make API requests on behalf of the user 12 | 13 | By the end of this guide, you will be able to: 14 | 15 | 1. Generate authorization codes 16 | 1. Have Adobe prompt users for consent 17 | 1. Handle the OAuth 2.0 server callback 18 | 1. Generate access tokens 19 | 1. Use refresh tokens to generate access tokens 20 | 1. Log out users 21 | 1. Call Adobe APIs 22 | 23 | 24 | 25 | 26 | 27 | 28 | ## Contents 29 | 30 | 1. [Prerequisites](#prerequisites) 31 | 1. [Register your application and enable APIs](#registeryourapplicationandenableapis) 32 | 1. [Retrieve application credentials](#retrieveapplicationcredentials) 33 | 1. [Convenience libraries](#conveniencelibraries) 34 | 1. [OAuth endpoints](#oauthendpoints) 35 | 1. [Generating authorization tokens](#generatingauthorizationtokens) 36 | 1. [Prompting the user for consent](#promptingtheuserforconsent) 37 | 1. [Handling the callback](#handlingthecallback) 38 | 1. [Generating access tokens](#generatingaccesstokens) 39 | 1. [Exchanging a refresh token for an access token](#exchangingarefreshtokenforanaccesstoken) 40 | 1. [Revoking authorization for end user](#revokingauthorizationforenduser) 41 | 1. [Complete examples for OAuth endpoints](#completeexamplesforoauthendpoints) 42 | 1. [Node.js Example](#nodejsexample) 43 | 1. [Python Example](#pythonexample) 44 | 45 | 46 | 47 | ## Prerequisites 48 | 49 | ### Register your application and enable APIs 50 | 51 | Your application needs to be registered with Adobe and a specific set of Adobe APIs need to be enabled to start making API calls. To enable these APIs: 52 | 53 | 1. [Go to the integration page in the Adobe Developer Console](https://www.adobe.com/go/devs_console_ui/integrations). 54 | 55 | - If you do not already have an Adobe ID, you will need to create one. 56 | 57 | 1. Create a new integration and select the APIs you want to enable. 58 | 1. Provide required information: 59 | 60 | - `Name`: Your application’s name. This will not be sent in your API requests. 61 | - `Description`: A simple description of your application. 62 | - `Platform`: Choose the platform your application runs on. 63 | - `Default redirect URI`: Choose a secure URL to receive callbacks from Adobe during the authentication process. This is the redirect URL that will be used if the requested `redirect_uri` does not match the redirect URI pattern or is not provided. It must be hosted on a secure (HTTPS) server, even if it is a localhost instance. For an example, check one of the [`samples`](samples). 64 | - `Redirect URI Pattern`: This is a URI path (or comma-separated list of paths) to which Adobe will attempt to redirect when the login flow is complete. To emphasize, this is a list of the **allowed** callback URL patterns, not the ones Adobe will attempt. It must be within your application domain, and all be on a secure (HTTPS) server. You must escape periods `.` with a backslash `\` (e.g. `https://mysite\.com/`). 65 | 66 | 67 | ### Retrieve application credentials 68 | 69 | After registering your application, [access the integration details page on the Adobe Developer Console](https://www.adobe.com/go/devs_console_ui/integrations) to retrieve the Client ID (API Key) and Client Secret values: 70 | 71 | ![Credentials page on the Adobe Developer Console](../Images/credentials_page.png?raw=true) 72 | 73 | 74 | ## Convenience libraries 75 | 76 | In addition to providing OAuth endpoints, Adobe provides OAuth libraries for some popular environments. 77 | 78 | - Node.js: [`passport-adobe-oauth2` Passport strategy on npm](https://www.npmjs.com/package/passport-adobe-oauth2) 79 | 80 | 81 | ## OAuth endpoints 82 | 83 | ### Generating authorization tokens 84 | 85 | The first step is to request the authorization token. This request sets the access scope and asks the user to grant permission to your application. 86 | 87 | In order to start this workflow, redirect the user to the Adobe's authorization endpoint: 88 | 89 | ``` 90 | https://ims-na1.adobelogin.com/ims/authorize 91 | ``` 92 | 93 | Include the following parameters: 94 | 95 | | Parameters | Description | 96 | | ------------- |:--------------------------------------------------------| 97 | | client_id | The Client ID obtained from the [Adobe Developer Console](https://www.adobe.com/go/devs_console_ui/integrations).| 98 | | redirect_uri | The URI to which the user agent is redirected once the authorization completes. Note that this URI must be HTTPS. The pattern is validated against the list of valid redirect URIs configured for your client.| 99 | | scope | The scope of the access request, expressed as a list of comma-delimited, case sensitive strings. See the [Scope Reference](oauth-scopes.md) for more information.| 100 | | response_type | The default `response_type` for the Authorization code flow is `code`. Use `token` for the Implicit grant flow. See below for more information. | 101 | | locale | Optional. The locale code for the authentication UI. Default is en_US.| 102 | | state | Optional. Client-defined state data that is replayed back to the client. It must not be longer than 255 characters. The value should be sent in JSON format, for example `state={“st”:some_alphanumeric_value}`. This parameter should be used to prevent [CSRF](https://tools.ietf.org/html/rfc6749#section-10.12) (Cross-Site Request Forgery).| 103 | 104 | _Note that Adobe OAuth does not support the practice of passing Base64 encoded `client_id` and `client_secret` using the HTTP BASIC authorization header._ 105 | 106 | #### Authorization code flow (`response_type = code`) 107 | 108 | The `code` response type used for "Authorization code flow" is often used by web server apps that are written in a server-side language and run on a server where the source code is not seen by the public. Thus, the application is able to use the client secret when communicating with the auth server. See below for the "Authorization code flow" steps: 109 | 110 | 1. Client initiates the flow by directing the resource owner's user-agent to the authorization endpoint. The request includes your client identifier, requested scope, optional local state information, and a redirect URI that the authorization server can use to send back the authorization code when authentication succeeds and authorization is granted. 111 | 1. The authorization server authenticates the resource owner through the user agent, which is typically a web browser. 112 | 1. If authentication is successful, the authorization server redirects the user-agent back to the client, using the redirect URI provided in the request. The response includes an authorization code, and any local state information that you sent with the request. 113 | 1. Your client requests an access token from the token endpoint. The client must authenticate itself by including its own client credentials in this request, as well as the authorization code received in the response to the initial request. 114 | 1. The authorization server validates both the client credentials and the authorization code. If valid, it responds with both an access token and a refresh token. 115 | 1. When the access token expires, you can use the refresh token to request a new access token. 116 | 117 | For more information, please refer to the [OAuth 2.0 specification](https://tools.ietf.org/html/rfc6749#section-4.1). 118 | 119 | Example URL (`code` response type): 120 | 121 | ``` 122 | https://ims-na1.adobelogin.com/ims/authorize 123 | ?client_id= 124 | &redirect_uri=https://oauth2-adobe.example.com/auth 125 | &scope=openid,creative_sdk 126 | &response_type=code 127 | ``` 128 | _Note: Refresh token and access token must be secured during transit and storage. Make sure to use TLS and to encrypt tokens while storing them at rest._ 129 | 130 | #### Implicit grant flow (`response_type = token`) 131 | 132 | On the other hand, the `token` response type used for "Implicit grant flow" is often used by SPAs (Single-Page Apps) or browser-based apps that run entirely in the browser. Since the source code is available to the browser, there's no way to hide the client secret. Thus, your app will receive the `access_token` right after the user provides consent. However, note that the `refresh_token` will not be provided for this flow. See below for the "Implicit grant flow" steps: 133 | 134 | 1. Client initiates the flow by directing the resource owner's user-agent to the authorization endpoint. The client includes its client identifier, requested scope, state, and a redirect URI to which Adobe Auth will send the user-agent back, once access is granted. 135 | 1. The authorization server authenticates the resource owner via the user-agent. 136 | 1. Assuming the resource owner authenticates, the authorization server redirects the user-agent back to the client using the redirect URI provided earlier. The redirection URI includes the access token in the URI fragment. 137 | 1. The user-agent follows the redirection instructions by making a request to the web-hosted client resource (which does not include the fragment). The user-agent retains the fragment information locally. 138 | 1. The web-hosted client resource returns a web page (typically an HTML document with an embedded script) capable of accessing the full redirection URI including the fragment retained by the user-agent, and extracting the access token and other parameters contained in the fragment. 139 | 1. The user-agent executes the script provided by the web-hosted client resource locally, which extracts the access token (no refresh token provided). 140 | 141 | For more information, please refer to the [OAuth 2.0 specification](https://tools.ietf.org/html/rfc6749#section-4.2). 142 | 143 | Example URL (`token` response type): 144 | 145 | ``` 146 | https://ims-na1.adobelogin.com/ims/authorize 147 | ?client_id= 148 | &redirect_uri=https://oauth2-adobe.example.com/auth 149 | &scope=openid,creative_sdk 150 | &response_type=token 151 | ``` 152 | _Note: Follow security best practices while storing the access token on the user’s browser. Make sure to use the browser’s session storage or cookies with the “secure” flag enabled._ 153 | 154 | ### Prompting the user for consent 155 | 156 | Once the request from the previous step is sent, Adobe will redirect the user to the Adobe ID sign-in page. After sign-in, the user will see a consent window showing the name of your application and the information that your application is requesting permission to access with the user's credentials: 157 | 158 | ![Adobe ID sign-in](../Images/login_screen.png?raw=true) ![Consent page](../Images/access_grant.png?raw=true) 159 | 160 | The user can either allow or refuse access. 161 | 162 | 163 | ### Handling the callback 164 | 165 | Adobe's OAuth 2.0 server will respond to your application's access request by using the redirect URI specified in the request. If the user has signed-in successfully and granted permissions, the OAuth 2.0 server will respond with an authorization code in the query string. If the user has not approved the request, the OAuth 2.0 server will send an error message. 166 | 167 | Example Authorization grant type response (`code` response type): 168 | 169 | ``` 170 | https://oauth2-adobe.example.com/auth?code=eyJ4NXUiOiJpbXNfbmExLWtleS.... 171 | ``` 172 | 173 | Example Implicit grant type response (`token` response type): 174 | 175 | ``` 176 | https://oauth2-adobe.example.com/auth#access_token=eyJ4NXUiOiJ...&token_type=bearer&expires_in=86399991 177 | ``` 178 | 179 | Example Authorization grant type error response (`code` response type): 180 | 181 | ``` 182 | https://oauth2-adobe.example.com/auth?error=access_denied 183 | ``` 184 | 185 | Example Implicit grant type error response (`token` response type): 186 | 187 | ``` 188 | https://oauth2-adobe.example.com/auth#error=access_denied 189 | ``` 190 | 191 | Note that, if you are using the "Implicit" grant type, you now have an `access_token` and your workflow ends here. 192 | 193 | ### Generating access tokens 194 | After receiving the authorization code, send a POST request to the token endpoint: 195 | 196 | ``` 197 | https://ims-na1.adobelogin.com/ims/token/ 198 | ``` 199 | 200 | Include the following parameters: 201 | 202 | | Parameters | Description | 203 | | ------------- |:--------------------------------------------------------| 204 | | code |The base-64 encoded `authorization_code` returned from the `/ims/authorize/` request.| 205 | | grant_type |The constant value `authorization_code`.| 206 | | client_id |The Client ID obtained from the [Adobe Developer Console](https://www.adobe.com/go/devs_console_ui/integrations).| 207 | | client_secret |The Client Secret obtained from the [Adobe Developer Console](https://www.adobe.com/go/devs_console_ui/integrations).| 208 | 209 | _Note that Adobe OAuth does not support the practice of passing Base64 encoded `client_id` and `client_secret` using the HTTP BASIC authorization header._ 210 | 211 | Example request: 212 | 213 | ``` 214 | POST /ims/token HTTP/1.1 215 | Host: ims-na1.adobelogin.com 216 | 217 | Content-Type: application/x-www-form-urlencoded 218 | grant_type=authorization_code 219 | &client_id= 220 | &client_secret= 221 | &code= 222 | ``` 223 | 224 | Example response: 225 | 226 | ``` 227 | HTTP/1.1 200 OK 228 | Content-Type: application/json;charset=UTF-8 229 | 230 | { 231 | "access_token": "eyJ4NXU...", 232 | "refresh_token": "eyJ4NXU...", 233 | "sub": "5BEB2BB...@AdobeID", 234 | "address": { 235 | "country": "US" 236 | }, 237 | "email_verified": "true", 238 | "name": "USERNAME", 239 | "token_type": "bearer", 240 | "given_name": "USERNAME", 241 | "expires_in": 86399985, 242 | "family_name": "USERNAME", 243 | "email": "USERNAME@example.com" 244 | } 245 | ``` 246 | 247 | Note that in addition to the `access_token` and `refresh_token`, the response also includes a JSON array of profile data that your `client_id` is authorized for and appropriate for the `scope` that you requested. 248 | 249 | ### Exchanging a refresh token for an access token 250 | 251 | The default expiry of access tokens is 24 hours. You can refresh an access token without prompting the user for permission again even if user is not present. The refresh token, by default, expires in 2 weeks. 252 | 253 | You can send a POST request to the token endpoint: 254 | 255 | ``` 256 | https://ims-na1.adobelogin.com/ims/token/ 257 | ``` 258 | 259 | Include the following parameters: 260 | 261 | | Parameters | Description | 262 | | ------------- |:--------------------------------------------------------| 263 | | refresh_token |The base-64 encoded `refresh_token` received in the response to the initial request for an access token.| 264 | | grant_type |The constant value `refresh_token`.| 265 | | client_id |The Client ID obtained from the [Adobe Developer Console](https://www.adobe.com/go/devs_console_ui/integrations).| 266 | | client_secret |The Client Secret obtained from the [Adobe Developer Console](https://www.adobe.com/go/devs_console_ui/integrations).| 267 | 268 | _Note that Adobe OAuth does not support the practice of passing Base64 encoded `client_id` and `client_secret` using the HTTP BASIC authorization header._ 269 | 270 | Example request: 271 | 272 | ``` 273 | POST /ims/token HTTP/1.1 274 | Host: ims-na1.adobelogin.com 275 | 276 | Content-Type: application/x-www-form-urlencoded 277 | grant_type=refresh_token 278 | &client_id= 279 | &client_secret= 280 | &refresh_token= 281 | ``` 282 | 283 | Example response: 284 | 285 | ``` 286 | HTTP/1.1 200 OK 287 | Content-Type: application/json;charset=UTF-8 288 | 289 | { 290 | "access_token": "eyJ4NXU...", 291 | "refresh_token": "eyJ4NXU...", 292 | "sub": "5BEB2BB...@AdobeID", 293 | "address": { 294 | "country": "US" 295 | }, 296 | "email_verified": "true", 297 | "name": "USERNAME", 298 | "token_type": "bearer", 299 | "given_name": "USERNAME", 300 | "expires_in": 86399985, 301 | "family_name": "USERNAME", 302 | "email": "USERNAME@example.com" 303 | } 304 | ``` 305 | 306 | Similar to above, note that in addition to the `access_token` and `refresh_token`, the response also includes a JSON array of profile data that your `client_id` is authorized for and appropriate for the `scope` that you requested. 307 | 308 | ### Revoking authorization for end user 309 | 310 | Users can revoke access to your application themselves by visiting [Connected Applications Page](https://accounts.adobe.com/security/connected-applications#). When the user launches your application next time, the authorization workflow will start from the beginning. 311 | 312 | ## Complete examples for OAuth endpoints 313 | 314 | The following samples demonstrate basic interaction with the Adobe OAuth endpoints. 315 | 316 | 317 | ### Node.js Example 318 | 319 | [Github repo](https://github.com/adobeio/adobeio-documentation/tree/master/auth/OAuth2.0Endpoints/samples/adobe-auth-node) where you can find a complete Node.js based web app example that uses Adobe OAuth. 320 | 321 | 322 | ### Python Example 323 | 324 | [Github repo](https://github.com/adobeio/adobeio-documentation/tree/master/auth/OAuth2.0Endpoints/samples/adobe-auth-python) where you can find a complete Python based web app example that uses Adobe OAuth. 325 | --------------------------------------------------------------------------------