Version 2.1 of Identity Server 4 was released a few weeks and this post is going to cover updating my sample project to the latest version. The starting point of the code can be found here. We are going to tackle this in sections as there are updates needed for an ASP.NET Core Update, Identity Server Update, and some broken bits in Angular.
ASP.NET Core Update
The sample projects were all on ASP.NET Core version 2.0.0. For each project right-click and select Edit ProjectName.csproj. Make the following change.
Before: <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" /> After: <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.3" />
Identity Server Update
Before: <PackageReference Include="IdentityServer4.EntityFramework" Version="2.0.0" /> After: <PackageReference Include="IdentityServer4.EntityFramework" Version="2.1.0" />
Next, need to add a couple of Entity Framework migrations to see if there were any data changes with the following commands from a command prompt in the Identity App project directory.
dotnet ef migrations add Configration21 -c ConfigurationDbContext -o Data/Migrations/IdentityServer/Configuration dotnet ef migrations add PersistedGrant21 -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrant
Turns out that there were no data changes for this version so if you are on version 2.0.0 you can skip this step.
Angular Issues
I’m not sure how I didn’t hit this issue on the last update post, but the Client App needs to be changed to use the new Angular HttpClient. I got the following error when trying to run the client application.
An unhandled exception occurred while processing the request.
NodeInvocationException: No provider for PlatformRef!
Error: No provider for PlatformRef!
at injectionError
Before: import { HttpModule } from '@angular/http'; After: import { HttpClientModule } from '@angular/common/http';
Next, in the imports array make the following change.
Before: HttpModule After: HttpClientModule
Next, in the webpack.config.vendor.js fille add the following to the vendor array.
'@angular/common/http'
The last changes are to the auth.service.ts and they are extensive so instead of going through them I’m just going to post the full class after all the changes.
import { Injectable, Component, OnInit, OnDestroy, Inject } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Observable } from 'rxjs/Rx'; import { Subscription } from 'rxjs/Subscription'; import { OidcSecurityService, OpenIDImplicitFlowConfiguration } from 'angular-auth-oidc-client'; @Injectable() export class AuthService implements OnInit, OnDestroy { isAuthorizedSubscription: Subscription; isAuthorized: boolean; constructor(public oidcSecurityService: OidcSecurityService, private http: HttpClient, @Inject('ORIGIN_URL') originUrl: string, @Inject('IDENTITY_URL') identityUrl: string ) { const openIdImplicitFlowConfiguration = new OpenIDImplicitFlowConfiguration(); openIdImplicitFlowConfiguration.stsServer = identityUrl; openIdImplicitFlowConfiguration.redirect_url = originUrl + 'callback'; openIdImplicitFlowConfiguration.client_id = 'ng'; openIdImplicitFlowConfiguration.response_type = 'id_token token'; openIdImplicitFlowConfiguration.scope = 'openid profile apiApp'; openIdImplicitFlowConfiguration.post_logout_redirect_uri = originUrl + 'home'; openIdImplicitFlowConfiguration.forbidden_route = '/forbidden'; openIdImplicitFlowConfiguration.unauthorized_route = '/unauthorized'; openIdImplicitFlowConfiguration.auto_userinfo = true; openIdImplicitFlowConfiguration.log_console_warning_active = true; openIdImplicitFlowConfiguration.log_console_debug_active = false; openIdImplicitFlowConfiguration.max_id_token_iat_offset_allowed_in_seconds = 10; this.oidcSecurityService.setupModule(openIdImplicitFlowConfiguration); if (this.oidcSecurityService.moduleSetup) { this.doCallbackLogicIfRequired(); } else { this.oidcSecurityService.onModuleSetup.subscribe(() => { this.doCallbackLogicIfRequired(); }); } } ngOnInit() { this.isAuthorizedSubscription = this.oidcSecurityService.getIsAuthorized().subscribe( (isAuthorized: boolean) => { this.isAuthorized = isAuthorized; }); } ngOnDestroy(): void { this.isAuthorizedSubscription.unsubscribe(); this.oidcSecurityService.onModuleSetup.unsubscribe(); } getIsAuthorized(): Observable<boolean> { return this.oidcSecurityService.getIsAuthorized(); } login() { console.log('start login'); this.oidcSecurityService.authorize(); } refreshSession() { console.log('start refreshSession'); this.oidcSecurityService.authorize(); } logout() { console.log('start logoff'); this.oidcSecurityService.logoff(); } private doCallbackLogicIfRequired() { if (typeof location !== "undefined" && window.location.hash) { this.oidcSecurityService.authorizedCallback(); } } get(url: string): Observable<any> { return this.http.get<any>(url, { headers: this.getHeaders() }); } put(url: string, data: any): Observable<any> { const body = JSON.stringify(data); return this.http.put<any>(url, body, { headers: this.getHeaders() }); } delete(url: string): Observable<any> { return this.http.delete<any>(url, { headers: this.getHeaders() }); } post(url: string, data: any): Observable<any> { const body = JSON.stringify(data); return this.http.post<any>(url, body, { headers: this.getHeaders() }); } private getHeaders() { let headers = new HttpHeaders(); headers = headers.set('Content-Type', 'application/json'); return this.appendAuthHeader(headers); } private appendAuthHeader(headers: HttpHeaders) { const token = this.oidcSecurityService.getToken(); if (token === '') return headers; const tokenValue = 'Bearer ' + token; return headers.set('Authorization', tokenValue); } }
With all those changes made run the following two commands in a command prompt in the Client App project directory.
node node_modules/webpack/bin/webpack.js --config webpack.config.vendor.js node node_modules/webpack/bin/webpack.js
Wrapping up
This post ended up being more about Angular than Identity Server, but it is nice to have everything upgraded to the latest and working.
The files in the completed can be found here.
Also published on Medium.