在我的代码中,我正在实现SSO登录。我有auth.service
,它在app.module.ts的app initializer
内部给出。我有代码流,可以访问该服务,并在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时,我应该能够获得访问令牌。但它会再次刷新该应用程序。该如何解决?
答案 0 :(得分:0)
编辑1: 您是否忘记了从getAuthToken()方法内部“返回”承诺? 对我来说,您好像正在调用getAuthToken,但获得null。
编辑2: 我看不到http.post有任何东西可以导致应用刷新。 唯一会导致重新加载的内容是此行
location.href = 'https://secureURLhere/authorize?' + params.join('&');
我觉得问题在于这里是否满足条件:
location.href.includes('?code=')
设置参数时,您可能要检查getAuthToken中的该部分。我认为您得到的是&code = 而不是预期的?code = 我可能错了。
编辑3
看看代码,我猜这就是POST请求的过程:
POST https://secureURLhere/token HTTP1.1
(Below is body part)
grant_type=authorization_code&code=code&client_id=abcde&client_secret=12345
您可以在chrome开发工具的“网络”标签中对其进行检查以进行验证。将其显示给您的API人员,或查看API文档以了解期望的内容。对于用户定义的标头,应为HttpHeaders类型,并且应为对象内部具有“ headers”属性的http.post()的第三个参数。默认情况下,http客户端会为您设置一些标题。
有关其工作方式,http.post返回一个可观察的对象,您可以订阅该对象。在您的情况下,您正在遵守可观察的承诺并进一步处理它。
哪种类型的可观测?如果您要问的话,这取决于Api发送的实际响应。它可以是可观察到的字符串(可观察到的),可观察到的Blob或可观察到的具有完整http响应(Observable
答案 1 :(得分:0)
有很多事情在您的代码中不起作用。对于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
}
}