Angular 使用 adal-angular4 和刷新令牌

Angular with adal-angular4 and refresh token

我正在使用以下包在 Angular 应用程序中实施 Azure AD 身份验证:

https://www.npmjs.com/package/adal-angular4

令牌在 10-20 分钟后过期。还有另一个讨论类似问题的线程,但我根本找不到有效的解决方案。老实说,在阅读 post 时,由于隐式流的性质,我什至不确定它是否可行。欢迎大家指点。

我有 Azure 重定向到的 authredirect 页面:

ngOnInit() {

    this.adal.handleWindowCallback();

    sessionStorage.setItem("adal.username",this.adal.userInfo.userName);

    this.loginService.userLoggedIn(this.adal.userInfo.userName);
    console.log("in authredirect. setting user in storage:"+this.adal.userInfo.userName);
    var url = sessionStorage.getItem("adal.return.url");

    console.log(url);

    setTimeout(() => {
      this._zone.run(
        () => this.router.navigate([url])
      );
    }, 500);
  } 

在我的 app.module.ts 我有以下内容:

 providers: [
    AdalService, 
      AuthenticationGuard,
      { provide: HTTP_INTERCEPTORS, useClass: AuthenticationInterceptor, multi: true }

在我的app.component构造函数中:

this.adalService.init(environment.adalConfig);

我的认证卫士:

export class AuthenticationGuard implements CanActivate {
  constructor(private adal: AdalService, private route: ActivatedRoute) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {

    if (this.adal.userInfo.authenticated) {
      return true;
    }

    console.log("Adal Login");
    var url = state.url;
    console.log(url);
    sessionStorage.setItem("adal.return.url",url);

    this.adal.login();

    console.log('AuthGuard'+this.adal);

    return false;
  }
}

最后是我的 app.routing.ts:

{
  path: 'chartering',
  loadChildren: './views/chartering/chartering.module#CharteringModule',
   canActivate: [AuthenticationGuard]
},

你很幸运,我以前也遇到过同样的问题,我花了几周时间才解决它。要获取访问令牌和刷新令牌,您需要使用 Microsoft 的 MSAL library instead of ADAL. There is absolutely no way to refresh your token without using MSAL. Microsoft's MSAL library is useless though. I wrote a simplified version from scratch specifically for my Angular application. I uploaded it to github for you. MsalService.ts。希望你能用得上。

基本上,只要您需要身份验证令牌,就可以使用 msalService.acquireToken 函数。如果该函数没有返回令牌,则用户应该注销。使用 msalService.loginmsalService.logout 可以让用户登录或注销。

由于 CORS 限制,您无法从应用程序的客户端请求访问令牌或刷新令牌。我在我的服务器上创建了端点来发出请求。

[HttpPost, Route("AccessToken")]
public async Task<HttpResponseMessage> GetAccessToken(AccessTokenRequest accessTokenRequest)
{
    HttpClient httpClient = new HttpClient();

    var content = new List<KeyValuePair<string, string>>
    {
        new KeyValuePair<string, string>("grant_type", "authorization_code"),
        new KeyValuePair<string, string>("client_id", "<insert_your_client_id>"),
        new KeyValuePair<string, string>("code", accessTokenRequest.AuthorizationCode),
        new KeyValuePair<string, string>("redirect_uri", RemoveHashFromUri(accessTokenRequest.RedirectUri)),
        new KeyValuePair<string, string>("client_secret", "<insert_your_client_secret>"),
        new KeyValuePair<string, string>("scope", accessTokenRequest.Scope)
    };

    var response = await httpClient.PostAsync($"https://login.microsoftonline.com/{your_tenant_id}/oauth2/v2.0/token", new FormUrlEncodedContent(content));

    return response;
}

[HttpPost, Route("RefreshToken")]
public async Task<HttpResponseMessage> RefreshToken(AccessTokenRequest accessTokenRequest)
{
    HttpClient httpClient = new HttpClient();

    var content = new List<KeyValuePair<string, string>>
    {
        new KeyValuePair<string, string>("grant_type", "refresh_token"),
        new KeyValuePair<string, string>("client_id", "<insert_your_client_id>"),
        new KeyValuePair<string, string>("refresh_token", accessTokenRequest.AuthorizationCode),
        new KeyValuePair<string, string>("client_secret", "<insert_your_client_secret>"),
    };

    var response = await httpClient.PostAsync($"https://login.microsoftonline.com/{your_tenant_id}/oauth2/v2.0/token", new FormUrlEncodedContent(content));

    return response;
}

private string RemoveHashFromUri(string redirectUri)
{
    if (string.IsNullOrWhiteSpace(redirectUri))
    {
        return null;
    }

    if (redirectUri.Contains("#"))
    {
        return redirectUri.Substring(0, redirectUri.IndexOf("#"));
    }

    return redirectUri;
}

public class AccessTokenRequest
{
    public string AuthorizationCode { get; set; }
    public string RedirectUri { get; set; }
    public string Scope { get; set; }
}

在应用程序组件的构造函数或 ngOnInit() 中,您需要这段代码来处理用户实际登录 Microsoft 时的回调。使用 Microsoft 在 url 哈希中返回的令牌,您可以获得访问令牌。

let authorizationCallback: IAuthorizationCallback = this.msalService.processAuthorizationCallback();

if (authorizationCallback.code) {
  // call out to your server for an access token
  this.resourceFactory.create("Auth/AccessToken").post({
    authorizationCode: authorizationCallback.code,
    redirectUri: this.msalService.getRedirectUrl(),
    scope: this.msalService.getScopes()
  }).then((json: any) => {

    try {
      this.msalService.cacheAuthentication(json);
    } catch (error) {
      // handle error
    }
  }).catch((error: any) => {
    // handle error
  });
} else if (authorizationCallback.error) {
  // handle error. Check authorizationCallback.error and authorizationCallback.error_description
}

如果您有任何问题,请告诉我。