From 7bb91c78a1bd5e7a17ca8103fa11e1a23ea812a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Val=C3=A9rian=20Girard?= Date: Tue, 25 Feb 2020 09:36:03 +0100 Subject: [PATCH] Add client_secret_basic auth exchangeCode Method. See related IdentityModel/oidc-client-js#892 --- src/JsonService.js | 8 +++++++- src/OidcClientSettings.js | 8 +++++++- src/TokenClient.js | 26 ++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/JsonService.js b/src/JsonService.js index 810d99e5..eb76bda0 100644 --- a/src/JsonService.js +++ b/src/JsonService.js @@ -96,7 +96,7 @@ export class JsonService { }); } - postForm(url, payload) { + postForm(url, payload, basicAuth) { if (!url){ Log.error("JsonService.postForm: No url passed"); throw new Error("url"); @@ -197,6 +197,12 @@ export class JsonService { } req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + + if (basicAuth !== undefined) + { + req.setRequestHeader("Authorization", "Basic " + btoa(basicAuth)); + } + req.send(body); }); } diff --git a/src/OidcClientSettings.js b/src/OidcClientSettings.js index de6ded54..56ac20ea 100644 --- a/src/OidcClientSettings.js +++ b/src/OidcClientSettings.js @@ -10,6 +10,7 @@ const OidcMetadataUrlPath = '.well-known/openid-configuration'; const DefaultResponseType = "id_token"; const DefaultScope = "openid"; +const DefaultClientAuthentication = "client_secret_post" // The default value must be client_secret_basic, as explained in https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication const DefaultStaleStateAge = 60 * 15; // seconds const DefaultClockSkewInSeconds = 60 * 5; @@ -20,6 +21,7 @@ export class OidcClientSettings { // client related client_id, client_secret, response_type = DefaultResponseType, scope = DefaultScope, redirect_uri, post_logout_redirect_uri, + client_authentication = DefaultClientAuthentication, // optional protocol prompt, display, max_age, ui_locales, acr_values, resource, response_mode, // behavior flags @@ -46,6 +48,7 @@ export class OidcClientSettings { this._scope = scope; this._redirect_uri = redirect_uri; this._post_logout_redirect_uri = post_logout_redirect_uri; + this._client_authentication = client_authentication; this._prompt = prompt; this._display = display; @@ -98,7 +101,10 @@ export class OidcClientSettings { get post_logout_redirect_uri() { return this._post_logout_redirect_uri; } - + get client_authentication() { + return this._client_authentication; + } + // optional protocol params get prompt() { diff --git a/src/TokenClient.js b/src/TokenClient.js index 5cb17f20..c2404bae 100644 --- a/src/TokenClient.js +++ b/src/TokenClient.js @@ -20,10 +20,17 @@ export class TokenClient { exchangeCode(args = {}) { args = Object.assign({}, args); + var basicAuth = undefined; + var urlQuery = ""; + args.grant_type = args.grant_type || "authorization_code"; args.client_id = args.client_id || this._settings.client_id; + args.client_secret = args.client_secret || this._settings.client_secret; args.redirect_uri = args.redirect_uri || this._settings.redirect_uri; + var client_authentication = args._client_authentication || this._settings._client_authentication; + delete args._client_authentication; + if (!args.code) { Log.error("TokenClient.exchangeCode: No code passed"); return Promise.reject(new Error("A code is required")); @@ -40,11 +47,26 @@ export class TokenClient { Log.error("TokenClient.exchangeCode: No client_id passed"); return Promise.reject(new Error("A client_id is required")); } + if (!args.client_secret && client_authentication == "client_secret_basic") { + Log.error("TokenClient.exchangeCode: No client_secret passed"); + return Promise.reject(new Error("A client_secret is required")); + } + + + // Sending the client credentials using the Basic Auth method + if(client_authentication == "client_secret_basic") + { + basicAuth = args.client_id + ':' + args.client_secret; + urlQuery = "?grant_type=" + encodeURIComponent(args.grant_type) + + "&redirect_uri="+ encodeURIComponent(args.redirect_uri) + + "&code="+ encodeURIComponent(args.code); + + args = {}; + } return this._metadataService.getTokenEndpoint(false).then(url => { Log.debug("TokenClient.exchangeCode: Received token endpoint"); - - return this._jsonService.postForm(url, args).then(response => { + return this._jsonService.postForm(url + urlQuery, args, basicAuth).then(response => { Log.debug("TokenClient.exchangeCode: response received"); return response; });