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.login
和 msalService.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
}
如果您有任何问题,请告诉我。
我正在使用以下包在 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.login
和 msalService.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
}
如果您有任何问题,请告诉我。