首页 > 解决方案 > 代码流身份验证 Angular 8 无法获取访问令牌

问题描述

在我的代码中,我正在实现 SSO 登录。我有auth.service,它app initializer在 app.module.ts 中给出。我有代码流,我可以访问服务,获取 url 中的代码。现在我想发送一个带有body将返回访问令牌的发布请求。但是一旦发布请求被击中,应用程序就会刷新并且该过程再次开始。它在尝试多次后退出循环并说Authorization code has expired. 我的代码如下: 在 app.module.ts 文件中

export function appsso(http: HttpClient, authService: AuthService) {
return (): Promise<any> => {
return authService.init()
};

 {provide: APP_INITIALIZER, useFactory: appsso, deps: [HttpClient, AuthService], multi: true}

在 authService 文件中

constructor(private http: HttpClient) {}

  init() {
    return new Promise<void>((resolve, reject) => {
    console.log('init is called');
    if (localStorage.getItem('token')) {              // if we have token, its good to go
      console.log('good to go');
      } else {
      if (!location.href.includes('?code=')){        // if url contains code
         const params = [
        'response_type=code',
        'client_id=abcde',
        'scope=openid profile',
        'redirect_uri=https://URLhere/a.0/',
        ];
        location.href = 'https://secureURLhere/authorize?' + params.join('&');      
        return 
      } else {
        const code = window.location.href.split('=')[1];     //split url to extract code
        return this.getAuthToken(code).then(data): any => {
        localStorage.setItem('tokenData', data);
        console.log('access token received');
        resolve();}, error ((err) => {
        console.log ('error occured');
        reject();
      }    
    }
  }
getAuthToken(code: string){
  let body: HttpParams = new HttpParams();
  body = body.append('grant_type', 'authorization_code')
  body = body.append('code', code)
  body = body.append('client_id', 'abcde')
  body = body.append('client_secret', '12345');
  return this.http.post('https://secureURLhere/token', body).toPromise();   //making post call
}

也是header类型'Content-Type': 'application/x-www-form-urlencoded'当 Post API 被命中时,我应该能够获得访问令牌。但它会再次刷新应用程序。如何解决?

标签: angulartypescriptpostsingle-sign-onangular8

解决方案


有很多东西在您的代码中不起作用。对于 if 语句的每一端,你应该返回一些东西。否则可能会卡住。此外,有时您需要在 if 语句中返回以防止嵌套,通过这样做,您的代码将更易于阅读(大部分时间)

您的服务的代码将是这样的:

import { HttpClient, HttpParams } from '@angular/common/http';

export interface AuthTokenResponse {
  access_token: string;
  id_token: string;
  expire_in: number;
  token_type: string;
}

class AuthService {
  constructor(private http: HttpClient) {}

  init() {
    return new Promise<void>((resolve, reject) => {
      // Check if token is in local storage
      if (localStorage.getItem('auth-token')) {
        // We have a token, so can continue
        return resolve();
      }

      // Create object from the URL query parameters
      const params = window.location.search
        .substr(1)
        .split('&')
        .reduce((prev, current) => {
          const [key, value] = current.split('=');
          if (key || (value !== undefined && value !== null)) {
            prev[key] = value;
          }
          return prev;
        }, {});

      // Check if the code is in the parameters
      if (params && params['code']) {
        // Code present. Use code to get Auth token
        return this.getAuthToken(params['code']).then(
          (data) => {
            // We get a access token. Save the token to the local storage
            localStorage.setItem('auth-token', JSON.stringify(data));
            resolve();
          },
          (err) => {
            // Something went wrong
            reject();
          }
        );
      }

      // No token was present in the parameters, so redirect to SSO URL
      const redirectParams = new HttpParams()
        .set('response_type', 'code')
        .set('client_id', 'abcde')
        .set('scope', 'openid profile')
        .set('redirect_uri', 'https://URLhere/a.0/');

      location.href =
        'https://secureURLhere/authorize?' + redirectParams.toString();
      return reject();
    });
  }

  getAuthToken(code: string): Promise<AuthTokenResponse> {
    // Create the body used tor the URL to get the auth token
    const body = new HttpParams()
      .append('grant_type', 'authorization_code')
      .append('code', code)
      .append('client_id', 'abcde')
      .append('client_secret', '12345');

    // Send API Post request to SSO API
    return this.http
      .post<AuthTokenResponse>('https://secureURLhere/token', body)
      .toPromise(); //making post call
  }
}


推荐阅读