Callback redirect not working with angular app on IIS

Hello,

I’m developing an application with Angular 8 (And .Net framework), where I integrated an OKTA authentication layer, the okta client it’s SPA type, and it works perfectly in local, while serving the app from visual studio. But for some reason, after deploying the app to one of our servers (And re configuring the redirect parameters), it doesn’t work properly. It loads the okta login page, and after logged, it tries to resolve the “URL/callback#tokenID” URL, but it gets stuck, if I refresh it, I get a 404.

Could I be missing some kind of rewrite or redirection rule or configuration on IIS?

I’m using windows server 2012 R2 and IIS version 8.5xxxx

Thanks in advantage!

When deployed on IIS, are you using https?

Hello Andrea,

No, I’m using “http” in both cases (Local and server). I have also these rules in the okta config file:
pkce: false,
cookies: {
secure: false
}

Cheers.

I think the issues are on IIS, it could be breaking the params from the “url/callback#idToken=xxxxxxxxx”. Basically, that’s returning a 404, I’ve been trying using a rewrite rule to receive whatever url containing “callback”, and send to “url/callback”.

Same result.

I’m still investigating about this, with no better results, tried several things on IIS config, different okta config. But similar result. The callback with id returned by Okta, is not getting processed properly by the app. Could be that the callback is not getting returned properly to the client side (Angular).

I’m using this library: import { OktaAuthService } from “@okta/okta-angular”;

And I’ve seen another choice from my side could be trying out this another one:

import * as OktaAuth from ‘@okta/okta-auth-js’;

Any clues from somebody? We’re talking about angular 8 and IIS, there has to be someone used to that config…

I would half wonder if its worth testing if this is specific to the hash fragment, or if you’d also have trouble receiving a query parameter at the callback route, but to do so, you would need to switch to using PKCE flow, since implicit flow will always use fragments.

Is the Angular side handling the callback (to get the token), or .NET? From what I understand, hash fragments will not be sent server side (client side only), so you may need to switch to authorization code flow if you are trying to get the tokens directly on the .NET side. Similar conversation found in Auth0’s forum: The redirect response does not send the hash fragment (tokens) to the server-side - #2 by jmangelo - Auth0 Community

Hey, I’m handling the token and all the okta layer in the Angular side, not in .Net. And about the hash fragment, I managed to remove the “#” (HashLocationStrategy), now the url for the callback it’s being sent, but apparently the response is not getting processed properly, this is the url where it gets stuck:

url/login/callback?code=VwhBEQLQov52dQnuj7Fxxxxx&state=dfohOdPMxxx

But from there, maybe it’s not reaching the angular side properly (Maybe due to IIS, or some wrong config in angular).

I was using the angular okta library (@okta/okta-angular") and for the callback, the “OktaCallbackComponent” from the same library. That DOESN’T work with IIS, unless there’s a specific config required for that (Not present in any doc), I’ve tried using another library: “@okta/okta-auth-js”, and doing manually what the callbackComponent should be doing, I made it work on IIS. Is there an explanation for that? Is Okta, using the angular library, fully compatible with IIS? Is it tested in all the IIS versions?

And Angular is correctly configured to use /login/callback as the callback route? Do you get any errors on the callback route?

Of course, it works locally served with visual studio (no errors), so it’s not an Okta/Angular config issue (Unless IIS requires some extra or specific config that I’m missing), but after removing the okta-angular library and not using the OktaCallbackComponent, using the code taken from this repo: GitHub - beyondJohn/OktaAngularIntegration: Using Okta OAuth to secure an Angular 8 app using {useHash:true} routing strategy .
It works after deploying it on IIS. Now I have to investigate (Or hopefully someone from the OKTA team could provide some guidance to us, as we’re clients), if IIS+Angular8+Okta-angular doesn’t work at all, or there’s a workaround.

I’ll be waiting for some more clues, in the meanwhile, I’m working and investigating the code to use the “okta-js” library.

Find here a piece of the code I’m using which doesn’t work (All the config matches with the okta client):

const appRoutes: Routes = [
    {
        path: "callback",
        // redirectTo: '/home', pathMatch: 'full',
        
        component: OktaCallbackComponent,
    },

    {
        // path: "",  redirectTo: '/home', pathMatch: 'full'
        path: ""
        , component: LoginComponent, canActivate: [ OktaAuthGuard] //Change back to oktaGuard
    },
    {
        path: "home", component: HomeComponent, canActivate: [OktaAuthGuard], resolve: { environmentsList: EnvironmentsResolver, pagesList: PagesResolver },
        children: 

export const appRoutingProviders: any[] = [
    PageGuard,
    ValidTokenGuard,
    { provide: LocationStrategy, useClass: PathLocationStrategy }
];
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes

-----------LOGIN.COMPONENT:
import { OktaAuthService } from "@okta/okta-angular";
import {
    Router
} from "@angular/router";
import { EmailRequest } from "./email.model";
import { AuthService } from "../common/services/auth.service";
import { environment } from "../../environments/environment";

//Test:
import * as OktaAuth from '@okta/okta-auth-js';

interface ResourceServerExample {
    label: string;
    url: string;
  }

@Component({

    templateUrl: "./login.component.html",
    styleUrls: ["./login.component.css"],
    // encapsulation: ViewEncapsulation.None
})

export class LoginComponent {

    resourceServerExamples: Array<ResourceServerExample>;
    userName: string;
    isAuthenticated: boolean;
    error: Error;
    loginRequest: EmailRequest;
    clickedState: boolean = false;
    isAnyError: boolean = true;
    errorMsg: string;

    constructor(public oktaAuth: OktaAuthService, private router: Router, private _authService: AuthService) {
        this.loginRequest = new EmailRequest("");
        this.oktaAuth.$authenticationState.subscribe(isAuthenticated => this.isAuthenticated = isAuthenticated);

      }

      async login(event: any) {
        try {
          await this.oktaAuth.signInWithRedirect();
          this.isAuthenticated = await this.oktaAuth.isAuthenticated();
        } catch (err) {
          console.error(err);
        }

        const accessToken = this.oktaAuth.getAccessToken();

      }

      async ngOnInit() {
        this.isAuthenticated = await this.oktaAuth.isAuthenticated(); // If this requires login, this shouldn't be true

        if (this.isAuthenticated) {
          const userClaims = await this.oktaAuth.getUser();
          this.userName = userClaims.name;
        } else {

        }
        this.loginRequest.email = await (await this.oktaAuth.getUser()).email;

        this.clickedState = true;
        let defaultUrl = environment.redirectUrl;
        let redirectUrl = this._authService.redirectUrl;

Thanks.

and the IIS server is configured to handle/host the callback route?