Skip to content

Commit e28fe40

Browse files
committed
added PKCE authorization
1 parent 0f51cf8 commit e28fe40

File tree

1 file changed

+37
-15
lines changed

1 file changed

+37
-15
lines changed

src/Services/CodeGrantService.php

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@
88

99
class CodeGrantService
1010
{
11+
function generateCodeVerifier() {
12+
return bin2hex(random_bytes(32));
13+
}
14+
15+
function generateCodeChallenge($code_verifier) {
16+
return rtrim(strtr(base64_encode(hash('sha256', $code_verifier, true)), '+/', '-_'), '=');
17+
}
18+
1119
/**
1220
* Checker for the CSRF token
1321
*/
@@ -35,20 +43,28 @@ public function flash(string $msg): void
3543
array_push($_SESSION['flash'], $msg);
3644
}
3745

38-
/**
39-
* DocuSign login handler
40-
*/
4146
public function login(): void
4247
{
43-
$provider = $this->getOauthProvider();
44-
$authorizationUrl = $provider->getAuthorizationUrl();
45-
// Get the state generated for you and store it to the session.
48+
if (isset($_SESSION['pkce_failed']) && $_SESSION['pkce_failed'] === true) {
49+
$provider = $this->getOauthProvider();
50+
$authorizationUrl = $provider->getAuthorizationUrl();
51+
} else {
52+
$codeVerifier = $this->generateCodeVerifier();
53+
$codeChallenge = $this->generateCodeChallenge($codeVerifier);
54+
$_SESSION['code_verifier'] = $codeVerifier;
55+
56+
$provider = $this->getOauthProvider();
57+
$authorizationUrl = $provider->getAuthorizationUrl([
58+
'code_challenge' => $codeChallenge,
59+
'code_challenge_method' => 'S256'
60+
]);
61+
}
4662
$_SESSION['oauth2state'] = $provider->getState();
4763
// Redirect the user to the authorization URL.
4864
header('Location: ' . $authorizationUrl);
4965
exit;
5066
}
51-
67+
5268
/**
5369
* Get OAUTH provider
5470
* @return DocuSign $provider
@@ -80,15 +96,19 @@ public function authCallback($redirectUrl): void
8096
}
8197
exit('Invalid OAuth state');
8298
} else {
99+
$tokenRequestOptions = [
100+
'code' => $_GET['code']
101+
];
102+
103+
// Add the code_verifier only for PKCE authorization
104+
if (!isset($_SESSION['pkce_failed']) || $_SESSION['pkce_failed'] === false) {
105+
$tokenRequestOptions['code_verifier'] = $_SESSION['code_verifier'];
106+
unset($_SESSION['pkce_failed']);
107+
}
108+
83109
try {
84110
// Try to get an access token using the authorization code grant.
85-
$accessToken = $provider->getAccessToken(
86-
'authorization_code',
87-
[
88-
'code' => $_GET['code']
89-
]
90-
);
91-
111+
$accessToken = $provider->getAccessToken('authorization_code', $tokenRequestOptions);
92112
$this->flash('You have authenticated with DocuSign.');
93113
// We have an access token, which we may use in authenticated
94114
// requests against the service provider's API.
@@ -117,7 +137,9 @@ public function authCallback($redirectUrl): void
117137
$_SESSION['ds_base_path'] = $account_info["base_uri"] . $base_uri_suffix;
118138
} catch (IdentityProviderException $e) {
119139
// Failed to get the access token or user details.
120-
exit($e->getMessage());
140+
$_SESSION['pkce_failed'] = true;
141+
$this->login();
142+
exit;
121143
}
122144
if (!$redirectUrl) {
123145
$redirectUrl = $GLOBALS['app_url'];

0 commit comments

Comments
 (0)