I am setting up a blue/green deployment and am trying to change the redirectUri
below based on the current url the user is viewing (redirectUri: this.router.url + '/callback',
). I am receiving Uncaught TypeError: Cannot read property 'router' of undefined
with the below configuration.
import { APP_BASE_HREF } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { CoreModule } from './@core/core.module';
import { AuthGuard } from './auth-guard.service';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { ThemeModule } from './@theme/theme.module';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { NbOAuth2AuthStrategy,
NbAuthModule,
NbOAuth2ResponseType,
NbOAuth2GrantType,
NbAuthOAuth2Token,
} from '@nebular/auth';
import { OAuth2LoginComponent } from './auth/oauth2-login.component';
import { OAuth2CallbackComponent } from './auth/oauth2-callback.component';
import { environment } from '../environments/environment';
import { Router } from '@angular/router';
@NgModule({
declarations: [AppComponent, OAuth2LoginComponent, OAuth2CallbackComponent ],
imports: [
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
NgbModule.forRoot(),
ThemeModule.forRoot(),
CoreModule.forRoot(),
NbAuthModule.forRoot({
forms: {},
strategies: [
NbOAuth2AuthStrategy.setup({
baseEndpoint: environment.authUrl,
name: 'cognito',
clientId: environment.clientId,
authorize: {
endpoint: '/oauth2/authorize',
responseType: NbOAuth2ResponseType.CODE,
scope: 'aws.cognito.signin.user.admin',
redirectUri: this.router.url + '/callback',
},
redirect: {
success: '/pages/dashboard',
},
token: {
endpoint: '/oauth2/token',
grantType: NbOAuth2GrantType.AUTHORIZATION_CODE,
class: NbAuthOAuth2Token,
redirectUri: this.router.url + '/callback',
},
refresh: {
endpoint: 'refresh-token',
grantType: NbOAuth2GrantType.REFRESH_TOKEN,
},
}),
],
}),
AppRoutingModule,
],
bootstrap: [AppComponent],
providers: [
AuthGuard,
{ provide: APP_BASE_HREF, useValue: '/' },
],
})
export class AppModule {
constructor(private router: Router) {}
}
I've also tried using redirectUri: window.location.origin + '/callback'
which works locally, but is null when built for production.
Note that class level decorators are applied to the constructor, before any instance of the class is created. So the router property isn't available for the decorator. In the example this.router.url + '/callback'
refers to the global this
instead, it's strange that there is no compilation errors.
Regarding window.location
, in the aot
compilation mode, which is default for the prod builds, expressions in the decorator are executed by Angular compiler at compile time, so window.location
isn't available there. Take a look at this GitHub issue: AOT replaces window.location object to null
As a workaround you can dynamically initialize the NbOAuth2AuthStrategy
, like:
@NgModule({
imports: [
...
NbAuthModule.forRoot({
strategies: [
NbOAuth2AuthStrategy.setup({
name: 'cognito'
})
],
...
})
],
...
})
export class AppModule {
constructor(
authService: NbAuthService, // force construction of the auth service
oauthStrategy: NbOAuth2AuthStrategy
) {
// window.location should be available here
this.oauthStrategy.setOpitions({
name: 'cognito',
...
});
}
}
As I found out, it's important to add the NbAuthService
to the constructor arguments as well as NbOAuth2AuthStrategy
. It looks like the service initializes the strategy during construction, so it should be constructed before the strategy initialization.
Also note that the setOptions()
method completely overrides the options from the module decorator, so the whole strategy initialization should be moved from the decorator to the constructor.
I've also found this GitHub issue, which helped me to find the correct solution.