Angular SSOLogin方法报错:HttpClient GET请求期望流却获undefined
Angular SSO登录请求报错排查与解决
问题描述
开发带SSOLogin单点登录功能的Angular认证服务时,检测到查询参数后调用SSOLogin方法触发以下错误:
TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable. RxJS 57 ssoLogin login.page.ts:104 ngOnInit login.page.ts:136 Angular 18 RxJS 49
错误发生在自定义头的HTTP GET请求阶段,已确认传入SSOLogin的username、access_token、id_token、consented_on参数均不为空,怀疑问题与请求头或HTTP请求结构相关。
相关代码片段
login.page.ts
/** First lifecycle hook */ ngOnInit() { const username: string = this.activatedRoute.snapshot.queryParamMap.get('username'); const access_token: string = this.activatedRoute.snapshot.queryParamMap.get('access_token'); const id_token: string = this.activatedRoute.snapshot.queryParamMap.get('id_token'); if (username && access_token && id_token) { this.ssoLogin(username, access_token, id_token, Math.floor(Date.now() / 1000).toString()); } } /** Method for logging in user retrieving query parameters (SSO Login) */ ssoLogin(username: string, access_token: string, id_token: string, consented_on: string) { this.authenticationSvc.SSOLogin(username, access_token, id_token, consented_on).subscribe({ next: (res: Response) => { if (res.success && res.rows && res.rows.includes('extra')) { if (res.rows['extra'] === 'USER_EXISTS') { this.clearLocalStorage(); this.requestLoginToken(this.authenticationSvc.consentedOn); } else if (res.rows['extra'] === 'USER_NOT_FOUND') { this.navUserNotFound(); } else if (res.rows['extra'] === 'REG_WAIT_APPROVAL') { this.toastService.showError('Component.Toast.account-pending-approval', 'warning'); } else { this.toastService.showError('Component.Toast.something-went-wrong'); } } else { this.toastService.showError('Component.Toast.something-went-wrong'); } }, error: (error: Error) => { console.log(error); this.toastService.showError('Component.Toast.something-went-wrong'); } }); }
authentication.service.ts
/** * SSO Login * @param username * @param access_token * @param id_token * @param consented_on * @returns Service response */ SSOLogin(username: string, access_token: any, id_token: string, consented_on: string) { let headers = { username: username, authorization: `Bearer ${access_token}`, jwt_token: id_token, consented_on: consented_on, client_id: environment.client_id, client_secret: environment.client_secret, clientKey: environment.clientKey }; return this.http.get<any>(environment.baseUrl + 'user/getExistence', { headers }) .pipe( map( (res: Response) => { if (res && res.success && res.extra === 'USER_EXISTS') { this.username = username; this.jwt = id_token; this.token = access_token; this.consentedOn = consented_on; } return res; } ), catchError(this.handleError)); } private handleError(error: HttpErrorResponse) { console.log(error); if (error.error === 'invalid_grant') { return throwError(false); } else { return throwError(true); } }
问题原因及解决方案
1. 错误处理函数上下文丢失
catchError中直接传入this.handleError会导致函数内部this指向异常,且RxJS的throwError需要传入工厂函数(RxJS 6+),直接传值会导致返回非Observable类型,触发报错。
修复方案:
- 用箭头函数包裹
handleError调用,确保上下文正确:catchError((error) => this.handleError(error)) - 同时修改
handleError的throwError调用方式:private handleError(error: HttpErrorResponse) { console.log(error); if (error.error === 'invalid_grant') { return throwError(() => false); } else { return throwError(() => true); } }
2. 请求头格式不符合Angular要求
Angular的HttpClient虽然支持自动将普通对象转为HttpHeaders,但复杂场景下可能转换失败,导致请求异常。
修复方案:
手动创建HttpHeaders实例:
import { HttpHeaders } from '@angular/common/http'; // ... let headers = new HttpHeaders({ username: username, authorization: `Bearer ${access_token}`, jwt_token: id_token, consented_on: consented_on, client_id: environment.client_id, client_secret: environment.client_secret, clientKey: environment.clientKey });
3. 响应类型不匹配
HttpClient.get<any>指定响应为any,但map操作中声明res: Response会导致类型冲突,可能引发处理逻辑异常。
修复方案:
统一响应类型,将map中的类型改为any,或定义对应接口:
map((res: any) => { if (res && res.success && res.extra === 'USER_EXISTS') { this.username = username; this.jwt = id_token; this.token = access_token; this.consentedOn = consented_on; } return res; })
4. 环境变量未正确加载
检查environment.client_id、environment.client_secret、environment.clientKey是否存在有效值,若为undefined会导致请求头字段异常。
调试方案:
在HTTP请求前打印头信息确认:
console.log('Request Headers:', headers);
内容的提问来源于stack exchange,提问作者Bill
相关产品推荐
相关产品推荐

