feat: add PKCE support for OAuth2 Authorization Code flows (#5361)
* Add PKCE support. * Fix tests * Update oauth2.md * Rename usePkce * Fix the BrokenComponent error * Update oauth2.md * Remove isCode variable. Remove uuid4 dependency. * Remove utils functions * Import crypto * Fix tests * Fix the tests * Cleanup * Fix code_challenge generation * Move code challenge and verifier to utils for mocks. Update tests. * Mock the PKCE methods in the utils file properly. * Add missing expect * use target-method spies * Add comments to explain test values. * Get rid of jsrsasign.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import win from "core/window"
|
||||
import { btoa, sanitizeUrl } from "core/utils"
|
||||
import { btoa, sanitizeUrl, generateCodeVerifier, createCodeChallenge } from "core/utils"
|
||||
|
||||
export default function authorize ( { auth, authActions, errActions, configs, authConfigs={} } ) {
|
||||
let { schema, scopes, name, clientId } = auth
|
||||
@@ -66,6 +66,18 @@ export default function authorize ( { auth, authActions, errActions, configs, au
|
||||
query.push("realm=" + encodeURIComponent(authConfigs.realm))
|
||||
}
|
||||
|
||||
if (flow === "authorizationCode" && authConfigs.usePkceWithAuthorizationCodeGrant) {
|
||||
const codeVerifier = generateCodeVerifier()
|
||||
const codeChallenge = createCodeChallenge(codeVerifier)
|
||||
|
||||
query.push("code_challenge=" + codeChallenge)
|
||||
query.push("code_challenge_method=S256")
|
||||
|
||||
// storing the Code Verifier so it can be sent to the token endpoint
|
||||
// when exchanging the Authorization Code for an Access Token
|
||||
auth.codeVerifier = codeVerifier
|
||||
}
|
||||
|
||||
let { additionalQueryStringParams } = authConfigs
|
||||
|
||||
for (let key in additionalQueryStringParams) {
|
||||
|
||||
@@ -120,13 +120,14 @@ export const authorizeApplication = ( auth ) => ( { authActions } ) => {
|
||||
}
|
||||
|
||||
export const authorizeAccessCodeWithFormParams = ( { auth, redirectUrl } ) => ( { authActions } ) => {
|
||||
let { schema, name, clientId, clientSecret } = auth
|
||||
let { schema, name, clientId, clientSecret, codeVerifier } = auth
|
||||
let form = {
|
||||
grant_type: "authorization_code",
|
||||
code: auth.code,
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret,
|
||||
redirect_uri: redirectUrl
|
||||
redirect_uri: redirectUrl,
|
||||
code_verifier: codeVerifier
|
||||
}
|
||||
|
||||
return authActions.authorizeRequest({body: buildFormData(form), name, url: schema.get("tokenUrl"), auth})
|
||||
|
||||
@@ -22,6 +22,7 @@ import { memoizedSampleFromSchema, memoizedCreateXMLExample } from "core/plugins
|
||||
import win from "./window"
|
||||
import cssEscape from "css.escape"
|
||||
import getParameterSchema from "../helpers/get-parameter-schema"
|
||||
import crypto from "crypto"
|
||||
|
||||
const DEFAULT_RESPONSE_KEY = "default"
|
||||
|
||||
@@ -859,3 +860,26 @@ export function paramToValue(param, paramValues) {
|
||||
|
||||
return values[0]
|
||||
}
|
||||
|
||||
// adapted from https://auth0.com/docs/flows/guides/auth-code-pkce/includes/create-code-verifier
|
||||
export function generateCodeVerifier() {
|
||||
return toBase64UrlEncoded(
|
||||
crypto.randomBytes(32)
|
||||
.toString("base64")
|
||||
)
|
||||
}
|
||||
|
||||
export function createCodeChallenge(codeVerifier) {
|
||||
return toBase64UrlEncoded(
|
||||
crypto.createHash("sha256")
|
||||
.update(codeVerifier, "ascii")
|
||||
.digest("base64")
|
||||
)
|
||||
}
|
||||
|
||||
function toBase64UrlEncoded(str) {
|
||||
return str
|
||||
.replace(/\+/g, "-")
|
||||
.replace(/\//g, "_")
|
||||
.replace(/=/g, "")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user