最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

angular - OAuth2 PKCE: Authorization Code Token Exchange -> The authenticated client id: [username] does not match the cl

programmeradmin2浏览0评论

So I am somewhat familiar with the OAuth2 authorization process, but I am facing a problem that I haven't encountered until now and haven't been able to solve.

We have a OAuth2 server in the corporate environment that we don't have direct access to. In my angular web application, I have tried to get an access token and ID token (OIDC). My website is registered as a redirect URI in the OAuth2 server. Problem now is: No matter what I have tried, I always get a authorization code, but fail to attain an access token/id token after all. I am positive that I send all the required information, but the error message I get is "The authenticated client id: [username] does not match the client id in the request body.", which seems to be an error message of an IBM OAuth2 implementation. The "username" part is exactly the corporate username that I have in the company, and the origin is probably the certificate that I am asked to send in the authentication process just before the authorization process (it is triggered automatically from the browser -> the certificate is loaded from a smartcard, I have to enter a pin for the whole process to continue).

I have tried to delete cookies. In the angular code, I started a new HttpClient in order to get rid of hidden, sent information. Nothing works. Noticably, the same last call to get the token in the browser, when copied as CURL and executed from command line, gives me the tokens! I have tried to manually delete cookies in the browser just before the last call, to no success (also cleared session storage etc.) Anyone's got an idea?

I also tried the angular-oauth2-oidc library from Mr. Steyer, I am getting the exact same error message in the end.

Here you have some angular debug code, in which I try to do as explained:


//preparation
const codeVerifier = await this.generateRandomString(43);
const codeChallenge = await this.generateCodeChallenge(codeVerifier);
  const clientId = 'my_client_id'; (given to meby the OAuth2 endpoint team)
  const redirectUri = encodeURIComponent('https://MY_REGISTERED_DOMAIN');
  const scope = encodeURIComponent('openid');
  const responseType = 'code';
  let state = 'state'; // Optional, for CSRF protection
  let code = '';
  const headers = new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' });

const authorizationUrl = `https://sso-endpoint/mga/sps/oauth/oauth20/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}&code_challenge=${codeChallenge}&code_verifier=${codeVerifier}&response_type=${responseType}&state=${state}&code_challenge_method=S256`;

let code = '';
this.http.get(authorizationUrl, { headers: headers, observe: 'response', responseType: 'text' })
      .subscribe((response: HttpResponse<string>) => {
        // Get the value of the `Location` header from the response
        const locationHeader = response.headers.get('Location');
        if (!locationHeader) {
          console.error('Location header not found in response.');
          return;
        }
  
        // Extract the value of the `code` query parameter from the URL
        const codeParam = new URL(locationHeader).searchParams.get('code');
        if (!codeParam) {
          console.error('Code parameter not found in response URL.');
          return;
        }
  
        // Handle the returned data with the extracted code parameter
        console.log('Code:', codeParam);
        code = codeParam;
      });

  const httpClient2 = new HttpClient(new HttpXhrBackend({ 
    build: () => new XMLHttpRequest() 
}));

// At this point, I have extracted an authorization code, which I now want to exchange for an access token -> this last request fails with the above mentioned error
  const aTokenUrl = `https://sso-endpoint/mga/sps/oauth/oauth20/token?client_id=${clientId}&redirect_uri=${redirectUri}&code_verifier=${codeVerifier}&grant_type=authorization_code&code=${code}`;
      httpClient2.post(aTokenUrl,{headers: headers,responseType: 'text'})
      .subscribe(data => {
        // Handle returned data -> if the request worked, I would use the result elsewise
        console.log(data);
      });

private async generateRandomString(length: number): Promise<string> {
  const allowedChars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~';
  let result = '';
  for (let i = 0; i < length; i++) {
    result += allowedChars.charAt(Math.floor(Math.random() * allowedChars.length));
  }
  return result;
}

private async generateCodeChallenge(codeVerifier: string): Promise<string> {
  const encodedVerifier = new TextEncoder().encode(codeVerifier);
  const hashedVerifier = await crypto.subtle.digest('SHA-256', encodedVerifier);
  const base64EncodedVerifier = btoa(String.fromCharCode(...new Uint8Array(hashedVerifier)));
  const codeChallenge = base64EncodedVerifier.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
  return codeChallenge;
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论