{"_id":"5d5ed7f6f19e5a001b3bae27","project":"564e5930c3553e0d003e53d0","version":{"_id":"564e5a9b1560880d008d30dc","project":"564e5930c3553e0d003e53d0","__v":27,"createdAt":"2015-11-19T23:26:19.166Z","releaseDate":"2015-11-19T23:26:19.166Z","categories":["564e5a9b1560880d008d30dd","566318e1f5ca460d00f41896","56631d08cd54d50d005015fa","56631d2a81ad7417006a202c","5668ba19fbd7680d009375f4","5668cb8b10bda80d00797ed9","5668cb9d10bda80d00797eda","56830d8a3f94e00d004e2a7a","56830d9072bb720d0091f594","56830d94cb4d190d0027698e","56830dc44aecbd0d00a464c5","569e90f3c9b43e0d00c4bab1","56a96d338791090d00113bab","56b12d8336d2580d00247877","56c36bf0a869d017002ea55b","56c36bf93d30210d00ea84bb","56c77749b935671700ff0304","56c7ab9e5652c217008e091a","56cb8bdad5c6241d00ef5e61","58aefce02470660f00b54539","58aefd0bebd7370f0078b954","59ca65ca4337830026edf24f","5c33cd9eb47ba20051ac8d64","5c33df728bec1d0063431c34","5c4783ef523219027055513a","5c4f35033400f3010203a999","5d1d0c9f19c3a0003aeb525a"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"Foundation","version_clean":"2.0.0","version":"2"},"category":{"_id":"5d1d0c9f19c3a0003aeb525a","project":"564e5930c3553e0d003e53d0","version":"564e5a9b1560880d008d30dc","__v":0,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2019-07-03T20:14:23.802Z","from_sync":false,"order":2,"slug":"app-integration-development","title":"App / Integration Development"},"user":"5c50c17c0a09bb000e8fd9d9","__v":0,"parentDoc":null,"metadata":{"title":"","description":"","image":[]},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2019-08-22T17:59:18.172Z","link_external":false,"link_url":"","sync_unique":"","hidden":false,"api":{"settings":"","results":{"codes":[]},"auth":"required","params":[],"url":""},"isReference":false,"order":9,"body":"# Overview #\n\n[Create an app](https://v2.developer.pagerduty.com/docs/how-to-build-an-app) to get access to OAuth 2 credentials.\n\nPKCE (Proof Key for Credential Exchange) is recommended for all Single Page Apps and Mobile apps and can also be used with a server side flow.\n\nPagerDuty supports OAuth 2.0’s [Authorization Code Grant](https://oauth.net/2/grant-types/authorization-code/) with [PKCE](https://oauth.net/2/pkce/) extension flow for all [third-party applications](https://v2.developer.pagerduty.com/docs/how-to-build-an-app) \n\nOAuth 2 is a 3 leg protocol that gives a user's identity the ability to establish limited authorization to specific resources on a system (in this case PagerDuty) for an application that operates on behalf of the user. \n\nThe following endpoints conform to the OAuth 2 protocol for Authorization Code Grant with PKCE\n[block:parameters]\n{\n  \"data\": {\n    \"0-0\": \"Authorization Endpoint\",\n    \"1-0\": \"Token Endpoint\",\n    \"1-1\": \"`https://app.pagerduty.com/oauth/token`\",\n    \"0-1\": \"`https://app.pagerduty.com/oauth/authorize`\"\n  },\n  \"cols\": 2,\n  \"rows\": 2\n}\n[/block]\n## What is PKCE? ##\n\nPKCE (pronounced pixie) stands for Proof Key for Code Exchange and allows a client side javascript, native mobile app, or server side web app to ensure that its code grant cannot be intercepted and exchanged for a token without knowing the Proof Key.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"PKCE Example Application\",\n  \"body\": \"[Sample Application in Javascript](https://github.com/PagerDuty/pagerduty-bulk-user-mgr-sample)\"\n}\n[/block]\n# Initiating the Access Grant : Leg 1 of 3\n[block:parameters]\n{\n  \"data\": {\n    \"0-0\": \"`client_id`\",\n    \"0-1\": \"An identifier issued when the [app is created](doc:how-to-build-an-app). \\n<span style=\\\"color:red\\\">Required</span>\",\n    \"1-0\": \"`redirect_uri`\",\n    \"1-1\": \"Registered with the app when OAuth 2.0 is added. PagerDuty will redirect here after a user grants or denies access to your app.\\n<span style=\\\"color:red\\\">Required</span>\",\n    \"2-0\": \"`response_type`\",\n    \"2-1\": \"Specifies the response type based on OAuth 2.0 flow. <span style=\\\"color:red\\\">Required. Value must be set to `code`.</span>\",\n    \"h-0\": \"Parameter\",\n    \"h-1\": \"Description\",\n    \"3-0\": \"`code_challenge`\",\n    \"4-0\": \"`code_challenge_method`\",\n    \"4-1\": \"Specifies that we are using PKCE SHA-256 Signature.\\n<span style=\\\"color:red\\\">Required. Value must be set to `S256`.</span>\",\n    \"3-1\": \"Base64 URL Encoded (without padding) string containing the SHA-256 digested form of the clients one-time random 128byte verifier (also in Base64URLEncoded (without padding) form)\\n<span style=\\\"color:red\\\">Required. See [Javascript PKCE Example Algorithm](#section-javascript-pkce-example-algorithm) below.  </span>\"\n  },\n  \"cols\": 2,\n  \"rows\": 5\n}\n[/block]\nThe flow is initiated by sending a GET request to authorization endpoint with query parameters set for `client_id`, `redirect_uri` (as defined in the app), `response_type=code` , as well as the PKCE extension fields (`code_challenge` and `code_challenge_method`)\n\nThe user will be required to a) login with credentials b) authorize the permissions requested by the client application.  \n```\nGET https://app.pagerduty.com/oauth/authorize?client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&response_type=code&code_challenge_method=S256&code_challenge\n```\n\n# Obtaining an Access Grant : Leg 2 of 3\n\nUpon initiating an access grant there are three possibilities:\n\n### #1 User Cannot Log In (Flow Stopped) ###\n\nThe flow ends without a valid user credential.\n\n### #2 User Logged In and Denied Permission to Client Application (Flow Stopped) ###\n\nThe flow ends with access denied. PagerDuty will redirect to the specified URI with `error` and `error_description` parameters:\n\n```\n{REDIRECT_URI}?error=access_denied&error_description=The+resource+owner+or+authorization+server+denied+the+request.&subdomain={ACCOUNT_SUBDOMAIN}\n```\n\n### #3 User Logged In and Approves Client Application Permission (Success) ###\n\nIf the user authorizes the client application, PagerDuty will redirect to the specified URI with the `code` (authorization code) in the URL:\n```\n{REDIRECT_URI}?code={AUTHORIZATION_CODE}&subdomain={ACCOUNT_SUBDOMAIN}\n```\nThe authorization code is valid for 10 minutes.\n\n# Exchanging Authorization Code For Access Token : Leg 3 of 3\n[block:parameters]\n{\n  \"data\": {\n    \"0-0\": \"`client_id`\",\n    \"1-0\": \"`code_verifier`\",\n    \"2-0\": \"`code`\",\n    \"2-1\": \"The authorization code issued upon a successful authorization request. \\n<span style=\\\"color:red\\\">Required for token request.</span>\",\n    \"3-0\": \"`redirect_uri`\",\n    \"3-1\": \"Registered with the app when OAuth 2 is added. \\n<span style=\\\"color:red\\\">Required </span>\",\n    \"1-1\": \"Original one-time, random 128 byte verifier (also in Base64URLEncoded without padding) used to generate the code_challenge for the authorization code request \\n<span style=\\\"color:red\\\">Required</span>\",\n    \"4-0\": \"`grant_type`\",\n    \"4-1\": \"<span style=\\\"color:red\\\">Required. Value must be set to`authorization_code` </span>\",\n    \"0-1\": \"An identifier issued when the app is created. \\n<span style=\\\"color:red\\\">Required</span>\"\n  },\n  \"cols\": 2,\n  \"rows\": 5\n}\n[/block]\nTo exchange the authorization code for an access token, send a POST request to the token endpoint. \n\nThe authorization code has a time to live of 10 minutes, and your POST request must be received within that time. \n\nAdditionally, specify the following query parameters when making the request: `client_id`,  `redirect_uri`, the `code` (authorization code) received from PagerDuty, `grant_type=authorization_code`, and finally the `code_verifier` that was generated to create the code_challenge originally.\n\n```\nPOST https://app.pagerduty.com/oauth/token?grant_type=authorization_code&client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&code={CODE}&code_verifier\n```\n\nThe access token will be included in a JSON response:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"access_token\\\":\\\"9937611c354d287d3ff509afdde5b1d6d500c73a67387d666ca1e8e3d502d516\\\",\\n  \\\"token_type\\\":\\\"bearer\\\",\\n  \\\"scope\\\":\\\"user\\\"\\n}\",\n      \"language\": \"json\",\n      \"name\": \"Authorized Response\"\n    }\n  ]\n}\n[/block]\n# Using an Access Token #\n\nOnce obtained, access tokens can be used to make [REST API](https://api-reference.pagerduty.com) requests on behalf of the user.\n\nWhen making an API request, include the version of the API in the `Accept` header. Access tokens must also be sent in the request as part of the `Authorization` header along with the `Bearer` token type, using this format:\n\n```\nAuthorization: Bearer 9937611c354d287d3ff509afdde5b1d6d500c73a67387d666ca1e8e3d502d516\nAccept: application/vnd.pagerduty+json;version=2\n```\n\nThe token can be used continuously to make requests until the user or app owner revokes it.\n\n# Sample Code\n\n**Javascript Application**\n[https://github.com/PagerDuty/pagerduty-bulk-user-mgr-sample](https://github.com/PagerDuty/pagerduty-bulk-user-mgr-sample)\n\n## Javascript PKCE Example Algorithm ##\n\nSince Javascript has a non-binary-unicode compatible Base64 operation, we provide a Javascript PKCE generation mechanism here:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"/*\\n *    // Example of using this function:\\n *\\n *   A generateCodePackagePromise().then(function(package) {\\n *     //\\n *     // These two fields are for leg1\\n *     //\\n *     package.code_challenge;\\n *     package.code_challenge_method;\\n *     //\\n *     // This will need to be stored in sessionStore  \\n *     // such that it is avalible when the page returns via redirect (leg2)\\n *     //\\n *     package.code_verifer; \\n *    })\\n *\\n */\\nfunction generateCodePackagePromise() {\\n    var base64Url = function(buffer) {\\n          /*\\\\\\n          |*|\\n          |*|  Base64 / binary data / UTF-8 strings utilities (#1)\\n          |*|  Based on Code From:\\n          |*|  https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding\\n          |*|\\n          |*|  Author: madmurphy\\n          |*|\\n          \\\\*/\\n\\n        var uint6ToB64 = function(nUint6) {\\n\\n            return nUint6 < 26 ?\\n                nUint6 + 65 :\\n                nUint6 < 52 ?\\n                nUint6 + 71 :\\n                nUint6 < 62 ?\\n                nUint6 - 4 :\\n                nUint6 === 62 ?\\n                43 :\\n                nUint6 === 63 ?\\n                47 :\\n                65;\\n\\n        }\\n        \\n        var base64EncArr = function(aBytes) {\\n\\n            var eqLen = (3 - (aBytes.length % 3)) % 3,\\n                sB64Enc = \\\"\\\";\\n\\n            for (var nMod3, nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) {\\n                nMod3 = nIdx % 3;\\n                /* Uncomment the following line in order to split the output in lines 76-character long: */\\n                /*\\n                  if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) { sB64Enc += \\\"\\\\r\\\\n\\\"; }\\n                */\\n                nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24);\\n                if (nMod3 === 2 || aBytes.length - nIdx === 1) {\\n                    sB64Enc += String.fromCharCode(uint6ToB64(nUint24 >>> 18 & 63), uint6ToB64(nUint24 >>> 12 & 63), uint6ToB64(nUint24 >>> 6 & 63), uint6ToB64(nUint24 & 63));\\n                    nUint24 = 0;\\n                }\\n            }\\n\\n            return eqLen === 0 ?\\n                sB64Enc :\\n                sB64Enc.substring(0, sB64Enc.length - eqLen) + (eqLen === 1 ? \\\"=\\\" : \\\"==\\\");\\n\\n        };\\n\\n\\n        var base64 = base64EncArr(new Uint8Array(buffer));\\n        var base64url_no_padding = base64.replace(/\\\\+/g, '-')\\n              .replace(/\\\\//g, '_')\\n              .replace(/=/g, '');\\n    \\n        return base64url_no_padding;\\n    }\\n    var gen128x8bitNonce = function() {\\n        var array = new Uint8Array(128); //( generate 1024bits 8*128\\n        window.crypto.getRandomValues(array);\\n        return array;\\n    };\\n\\n    var code_verifier = gen128x8bitNonce();\\n\\n    /* \\n       Note : We consider the code_verifier used for the purpose\\n       of generating a hash to be in the base64_url_no_padding format\\n       Since any random sequence of 1024bits can be mapped into a base64\\n       encoding and the standard recommends the code_verifier be specified\\n       in terms of the characters that base64_url_no_padding is made up\\n       of - the most effective way to create a code_verifier is by not\\n       generating a random sequence of the base64 characters but simply\\n       generate a 1024bit number sequence and convert it to base64 string.\\n    */\\n    var base64_verifier = base64Url(code_verifier.buffer);\\n    var encoder = new TextEncoder();\\n    var base64_arraybuffer = encoder.encode(base64_verifier);\\n\\n    return crypto.subtle.digest(\\\"SHA-256\\\", base64_arraybuffer).then(function(code_challenge){\\n\\n        return {\\n            code_verifer: base64_verifier,\\n            code_challenge: base64Url(code_challenge),\\n            code_challenge_method: \\\"S256\\\"\\n        }\\n    });\\n}\\n\",\n      \"language\": \"javascript\",\n      \"gist\": \"66f737c3b13646e3a81141cf6aa3b117\"\n    }\n  ]\n}\n[/block]","excerpt":"PKCE Authorization Code Grant For Public, Mobile, and Server Side use.","slug":"oauth-2-functionality-pkce","type":"basic","title":"OAuth 2: PKCE Flow"}

OAuth 2: PKCE Flow

PKCE Authorization Code Grant For Public, Mobile, and Server Side use.

# Overview # [Create an app](https://v2.developer.pagerduty.com/docs/how-to-build-an-app) to get access to OAuth 2 credentials. PKCE (Proof Key for Credential Exchange) is recommended for all Single Page Apps and Mobile apps and can also be used with a server side flow. PagerDuty supports OAuth 2.0’s [Authorization Code Grant](https://oauth.net/2/grant-types/authorization-code/) with [PKCE](https://oauth.net/2/pkce/) extension flow for all [third-party applications](https://v2.developer.pagerduty.com/docs/how-to-build-an-app) OAuth 2 is a 3 leg protocol that gives a user's identity the ability to establish limited authorization to specific resources on a system (in this case PagerDuty) for an application that operates on behalf of the user. The following endpoints conform to the OAuth 2 protocol for Authorization Code Grant with PKCE [block:parameters] { "data": { "0-0": "Authorization Endpoint", "1-0": "Token Endpoint", "1-1": "`https://app.pagerduty.com/oauth/token`", "0-1": "`https://app.pagerduty.com/oauth/authorize`" }, "cols": 2, "rows": 2 } [/block] ## What is PKCE? ## PKCE (pronounced pixie) stands for Proof Key for Code Exchange and allows a client side javascript, native mobile app, or server side web app to ensure that its code grant cannot be intercepted and exchanged for a token without knowing the Proof Key. [block:callout] { "type": "info", "title": "PKCE Example Application", "body": "[Sample Application in Javascript](https://github.com/PagerDuty/pagerduty-bulk-user-mgr-sample)" } [/block] # Initiating the Access Grant : Leg 1 of 3 [block:parameters] { "data": { "0-0": "`client_id`", "0-1": "An identifier issued when the [app is created](doc:how-to-build-an-app). \n<span style=\"color:red\">Required</span>", "1-0": "`redirect_uri`", "1-1": "Registered with the app when OAuth 2.0 is added. PagerDuty will redirect here after a user grants or denies access to your app.\n<span style=\"color:red\">Required</span>", "2-0": "`response_type`", "2-1": "Specifies the response type based on OAuth 2.0 flow. <span style=\"color:red\">Required. Value must be set to `code`.</span>", "h-0": "Parameter", "h-1": "Description", "3-0": "`code_challenge`", "4-0": "`code_challenge_method`", "4-1": "Specifies that we are using PKCE SHA-256 Signature.\n<span style=\"color:red\">Required. Value must be set to `S256`.</span>", "3-1": "Base64 URL Encoded (without padding) string containing the SHA-256 digested form of the clients one-time random 128byte verifier (also in Base64URLEncoded (without padding) form)\n<span style=\"color:red\">Required. See [Javascript PKCE Example Algorithm](#section-javascript-pkce-example-algorithm) below. </span>" }, "cols": 2, "rows": 5 } [/block] The flow is initiated by sending a GET request to authorization endpoint with query parameters set for `client_id`, `redirect_uri` (as defined in the app), `response_type=code` , as well as the PKCE extension fields (`code_challenge` and `code_challenge_method`) The user will be required to a) login with credentials b) authorize the permissions requested by the client application. ``` GET https://app.pagerduty.com/oauth/authorize?client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&response_type=code&code_challenge_method=S256&code_challenge ``` # Obtaining an Access Grant : Leg 2 of 3 Upon initiating an access grant there are three possibilities: ### #1 User Cannot Log In (Flow Stopped) ### The flow ends without a valid user credential. ### #2 User Logged In and Denied Permission to Client Application (Flow Stopped) ### The flow ends with access denied. PagerDuty will redirect to the specified URI with `error` and `error_description` parameters: ``` {REDIRECT_URI}?error=access_denied&error_description=The+resource+owner+or+authorization+server+denied+the+request.&subdomain={ACCOUNT_SUBDOMAIN} ``` ### #3 User Logged In and Approves Client Application Permission (Success) ### If the user authorizes the client application, PagerDuty will redirect to the specified URI with the `code` (authorization code) in the URL: ``` {REDIRECT_URI}?code={AUTHORIZATION_CODE}&subdomain={ACCOUNT_SUBDOMAIN} ``` The authorization code is valid for 10 minutes. # Exchanging Authorization Code For Access Token : Leg 3 of 3 [block:parameters] { "data": { "0-0": "`client_id`", "1-0": "`code_verifier`", "2-0": "`code`", "2-1": "The authorization code issued upon a successful authorization request. \n<span style=\"color:red\">Required for token request.</span>", "3-0": "`redirect_uri`", "3-1": "Registered with the app when OAuth 2 is added. \n<span style=\"color:red\">Required </span>", "1-1": "Original one-time, random 128 byte verifier (also in Base64URLEncoded without padding) used to generate the code_challenge for the authorization code request \n<span style=\"color:red\">Required</span>", "4-0": "`grant_type`", "4-1": "<span style=\"color:red\">Required. Value must be set to`authorization_code` </span>", "0-1": "An identifier issued when the app is created. \n<span style=\"color:red\">Required</span>" }, "cols": 2, "rows": 5 } [/block] To exchange the authorization code for an access token, send a POST request to the token endpoint. The authorization code has a time to live of 10 minutes, and your POST request must be received within that time. Additionally, specify the following query parameters when making the request: `client_id`, `redirect_uri`, the `code` (authorization code) received from PagerDuty, `grant_type=authorization_code`, and finally the `code_verifier` that was generated to create the code_challenge originally. ``` POST https://app.pagerduty.com/oauth/token?grant_type=authorization_code&client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&code={CODE}&code_verifier ``` The access token will be included in a JSON response: [block:code] { "codes": [ { "code": "{\n \"access_token\":\"9937611c354d287d3ff509afdde5b1d6d500c73a67387d666ca1e8e3d502d516\",\n \"token_type\":\"bearer\",\n \"scope\":\"user\"\n}", "language": "json", "name": "Authorized Response" } ] } [/block] # Using an Access Token # Once obtained, access tokens can be used to make [REST API](https://api-reference.pagerduty.com) requests on behalf of the user. When making an API request, include the version of the API in the `Accept` header. Access tokens must also be sent in the request as part of the `Authorization` header along with the `Bearer` token type, using this format: ``` Authorization: Bearer 9937611c354d287d3ff509afdde5b1d6d500c73a67387d666ca1e8e3d502d516 Accept: application/vnd.pagerduty+json;version=2 ``` The token can be used continuously to make requests until the user or app owner revokes it. # Sample Code **Javascript Application** [https://github.com/PagerDuty/pagerduty-bulk-user-mgr-sample](https://github.com/PagerDuty/pagerduty-bulk-user-mgr-sample) ## Javascript PKCE Example Algorithm ## Since Javascript has a non-binary-unicode compatible Base64 operation, we provide a Javascript PKCE generation mechanism here: [block:code] { "codes": [ { "code": "/*\n * // Example of using this function:\n *\n * A generateCodePackagePromise().then(function(package) {\n * //\n * // These two fields are for leg1\n * //\n * package.code_challenge;\n * package.code_challenge_method;\n * //\n * // This will need to be stored in sessionStore \n * // such that it is avalible when the page returns via redirect (leg2)\n * //\n * package.code_verifer; \n * })\n *\n */\nfunction generateCodePackagePromise() {\n var base64Url = function(buffer) {\n /*\\\n |*|\n |*| Base64 / binary data / UTF-8 strings utilities (#1)\n |*| Based on Code From:\n |*| https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding\n |*|\n |*| Author: madmurphy\n |*|\n \\*/\n\n var uint6ToB64 = function(nUint6) {\n\n return nUint6 < 26 ?\n nUint6 + 65 :\n nUint6 < 52 ?\n nUint6 + 71 :\n nUint6 < 62 ?\n nUint6 - 4 :\n nUint6 === 62 ?\n 43 :\n nUint6 === 63 ?\n 47 :\n 65;\n\n }\n \n var base64EncArr = function(aBytes) {\n\n var eqLen = (3 - (aBytes.length % 3)) % 3,\n sB64Enc = \"\";\n\n for (var nMod3, nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) {\n nMod3 = nIdx % 3;\n /* Uncomment the following line in order to split the output in lines 76-character long: */\n /*\n if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) { sB64Enc += \"\\r\\n\"; }\n */\n nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24);\n if (nMod3 === 2 || aBytes.length - nIdx === 1) {\n sB64Enc += String.fromCharCode(uint6ToB64(nUint24 >>> 18 & 63), uint6ToB64(nUint24 >>> 12 & 63), uint6ToB64(nUint24 >>> 6 & 63), uint6ToB64(nUint24 & 63));\n nUint24 = 0;\n }\n }\n\n return eqLen === 0 ?\n sB64Enc :\n sB64Enc.substring(0, sB64Enc.length - eqLen) + (eqLen === 1 ? \"=\" : \"==\");\n\n };\n\n\n var base64 = base64EncArr(new Uint8Array(buffer));\n var base64url_no_padding = base64.replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=/g, '');\n \n return base64url_no_padding;\n }\n var gen128x8bitNonce = function() {\n var array = new Uint8Array(128); //( generate 1024bits 8*128\n window.crypto.getRandomValues(array);\n return array;\n };\n\n var code_verifier = gen128x8bitNonce();\n\n /* \n Note : We consider the code_verifier used for the purpose\n of generating a hash to be in the base64_url_no_padding format\n Since any random sequence of 1024bits can be mapped into a base64\n encoding and the standard recommends the code_verifier be specified\n in terms of the characters that base64_url_no_padding is made up\n of - the most effective way to create a code_verifier is by not\n generating a random sequence of the base64 characters but simply\n generate a 1024bit number sequence and convert it to base64 string.\n */\n var base64_verifier = base64Url(code_verifier.buffer);\n var encoder = new TextEncoder();\n var base64_arraybuffer = encoder.encode(base64_verifier);\n\n return crypto.subtle.digest(\"SHA-256\", base64_arraybuffer).then(function(code_challenge){\n\n return {\n code_verifer: base64_verifier,\n code_challenge: base64Url(code_challenge),\n code_challenge_method: \"S256\"\n }\n });\n}\n", "language": "javascript", "gist": "66f737c3b13646e3a81141cf6aa3b117" } ] } [/block]