【发布时间】:2021-07-12 09:19:50
【问题描述】:
我一直在尝试将 state 和 code_challenge 添加到我们的流程中,但由于某种原因,我继续收到来自亚马逊的 invalid_request 回复。
我跟着这个Auth0 tutorial 去了一个发球台。
/**
* Converts buffer to Base64 URL encoded string
*
* @param {Buffer} buf The buffer to convert
* @returns {string}
*/
private base64URLEncode(str: any): string {
return str.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}
/**
* Generates a new code challenge
*
* @returns {string} The code challange string
*/
private generateCodeChallenge(): string {
if (!this._verifier) this._verifier = this.base64URLEncode(crypto.randomBytes(32));
return this.base64URLEncode(crypto.createHash('sha256').update(this._verifier).digest());
}
/**
* Generates the Authorization URL
*/
public generateAuthUrl(): string {
if (!this.config.clientId) throw new Error('Client ID is missing from configuration.');
if (!this.config.redirectUrl) throw new Error('Redirect URI is missing from configuration.');
if (!this._state) this._state = this.base64URLEncode(crypto.randomBytes(28));
return `${this.config.protocol}://signin.${
this.config.host
}/login?response_type=code&client_id=${this.config.clientId}&redirect_uri=${
this.config.redirectUrl
}&scope=${this._scope.join('%20')}&state=${
this._state
}&code_challenge_method=S256&code_challenge=${this.generateCodeChallenge()}`;
}
/**
* Verifies that the state matches
*
* @returns {boolean}
*/
public verifyState(state: string): boolean {
return this._state === state;
}
/**
* Retrieves a new OAuth Authorization Grant token
*/
public async getToken(code: string): Promise<UserAccessToken> {
if (!this.config.clientId) throw new Error('Client ID is missing from configuration.');
if (!this.config.redirectUrl) throw new Error('Redirect URI is missing from configuration.');
try {
const token = (await this.req.postform(
`/oauth2/token`,
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Cache-Control': 'no-store',
},
},
{
grant_type: 'authorization_code',
code,
client_id: this.config.clientId,
code_verifier: this._verifier,
redirect_uri: this.config.redirectUrl,
}
)) as UserAccessToken;
this._userAccessToken = token;
return token;
} catch (err) {
throw err;
}
}
在用代码交换令牌之前,一切都运行良好。我们重定向到我们托管的 UI 并成功取回代码。当我们将其换成令牌时,无论我尝试了什么,我们都会收到 invalid_request 响应。如果我删除代码挑战,一切都会按预期工作,所以我非常有信心这是导致问题的原因。
更新 1
这个函数在我们的 React 应用程序中的 useEffect 钩子内调用,如下所示:
useEffect(() => {
const authUrl = sdk.auth.generateAuthUrl();
console.log(authUrl);
if (!code) window.location.assign(authUrl);
console.log(`New Auth URL: ${authUrl}`);
sdk.auth
.getToken(code as string)
.then((token) => {
localStorage.setItem('sdk_access_token', JSON.stringify(token));
sdk.organizations.getUser().then((user) => {
setUser({ ...user });
history.push('/');
});
})
.catch((err) => console.log(err));
}, []);
这怎么可能? window.location.href 是否以某种方式对 URL 进行了编码?
【问题讨论】:
标签: node.js oauth-2.0 amazon-cognito