I am creating an app using angular with IdentityServer SSO provider in ASP.NET.
I am able to log the user in and get the user info from auth server: User info
And this is the method that is called when SSO redirects user back after login (the console.log is what shows the user info on previous image):
//Auth service
async completeAuthentication()
{
this.user = await this.manager.signinRedirectCallback();
console.log(this.user);
this.authNavStatusSource.next(this.isAuthenticated());
}
So in this place I have the user defined and everything should be ok but when I try to use the user username in header it shows up us undefined: Undefined user
And this is place where the console.log is called:
//Header component
ngOnInit(): void {
this.subscription = this.authService.authNavStatus$.subscribe(status => this.isAuthenticated = status);
this.name = this.authService.username; //this is pr
}
//Auth service
get username(): string
{
console.log(this.user);
return this.user != null ? this.user.profile.preferred_username : '';
}
Here are full files for auth service and header component:
auth.service.ts
import { Injectable } from '@angular/core';
import { UserManager, User } from 'oidc-client';
import { BehaviorSubject } from 'rxjs';
import { BaseService } from '../services/base.service';
import { ConfigService } from '../services/config.service';
@Injectable({
providedIn: 'root'
})
export class AuthService extends BaseService {
private authNavStatusSource = new BehaviorSubject<boolean>(false);
authNavStatus$ = this.authNavStatusSource.asObservable();
private manager = new UserManager
({
authority: this.configService.AuthAppUri,
client_id: 'angular_spa',
redirect_uri: 'http://localhost:4200/auth-callback',
post_logout_redirect_uri: 'http://localhost:4200',
response_type: "code",
scope: "openid profile email api.read",
filterProtocolClaims: true,
loadUserInfo: true
});
private user: User | null;
constructor(private configService: ConfigService)
{
super();
this.manager.getUser().then(user => {
this.user = user;
this.authNavStatusSource.next(this.isAuthenticated());
});
}
login(userName?: string)
{
let extraQueryParams = userName ?
{
userName: userName
} : {};
return this.manager.signinRedirect
({
extraQueryParams
});
}
async completeAuthentication()
{
this.user = await this.manager.signinRedirectCallback();
this.authNavStatusSource.next(this.isAuthenticated());
}
isAuthenticated(): boolean
{
return this.user != null && !this.user.expired;
}
get authorizationHeaderValue(): string
{
return this.user ? `${this.user.token_type} ${this.user.access_token}` : null;
}
get username(): string
{
console.log(this.user);
return this.user != null ? this.user.profile.preferred_username : '';
}
async logout()
{
await this.manager.signoutRedirect();
}
}
header.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { AuthService } from '../core/authentication/auth.service';
@Component({
selector: 'app-header',
template: `
<div >
<div >
<div routerLink="/">
LOGO
</div>
<div >
MENU
</div>
</div>
<div >
<div >
<a routerLink="/gameslist">Games</a>
<a routerLink="/login" *ngIf="!isAuthenticated"><b>Login</b></a>
<a routerLink="" *ngIf="isAuthenticated"><b>{{name}}</b></a>
</div>
</div>
</div>
`,
styles: [
'.navbar{ border-style: solid; border-width: 0px 0px 2px 0px; }'
]
})
export class HeaderComponent implements OnInit, OnDestroy {
name: string;
isAuthenticated: boolean;
subscription: Subscription;
constructor(public authService: AuthService) { }
ngOnInit(): void {
this.subscription = this.authService.authNavStatus$.subscribe(status => this.isAuthenticated = status);
this.name = this.authService.username;
}
async logout()
{
await this.authService.logout();
}
ngOnDestroy()
{
this.subscription.unsubscribe();
}
}
Why can't I use user in my header? What's interesting is that I used the same get username() method in home component and it works just fine so I really have no idea why can't I get it to work in header component.
CodePudding user response:
I guess that you actually can use username in your header. The problem, is that you are probably using it before it is 'instantiated'.
Try to insert this.name asignation inside the subscribtion, see how it goes:
this.subscription = this.authService.authNavStatus$
.subscribe(
status => {this.isAuthenticated = status;
this.name = this.authService.username;
});