angular - 代码流身份验证 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 被命中时,我应该能够获得访问令牌。但它会再次刷新应用程序。如何解决?
解决方案
有很多东西在您的代码中不起作用。对于 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
}
}
推荐阅读
- max - 将结果集从用户定义的函数传递到 max() 函数
- laravel - Laravel,迁移关系在某个时间结束
- javascript - 如何在模式中显示动态内容?
- python - 从一些 HTML 标签中提取文本
- postgresql - PostgreSQL 在多大程度上支持并行 DDL?
- java - 更新值为 List 的 HashMap 的条目
- c++ - 当统一块大小很小时,是否应该在 glUniform 上使用统一缓冲区对象?
- javascript - 允许和允许之间的 JavaScript 差异的 Google Chrome 权限设置(默认)
- python - 在 Python Plotly 中将数据点名称写入数据点的正上方
- linux - Apache 重写规则 .HTACCESS 文件