Angular and ASP.NET OWIN with Azure AD

43 views Asked by At

I recently came across a challenging problem. I was asked to add Azure Active Directory (AAD) authentication to an Authentication server using ASP.NET OWIN .NET Framework 4.7.2. Basically I have an Angular App and Authentication server. Angular will initiate authentication process when user clicks on Login for Other button. After that user will be redirect to ASP.NET OWIN Login Page which will Challenge user to authenticate against AAD. On successful authentication user will be redirected to Angular APP with necessary tokens and user details.

I'm using oidc-client in angular.

Angular Code

AuthService =>

import { User, UserManager, UserManagerSettings, Log, WebStorageStateStore} from 'oidc-client'
  constructor(private http: HttpClient) { 
    const settings: UserManagerSettings = {
      authority: 'https://localhost:44302',
      client_id:'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx',
      redirect_uri:'http://localhost:4200/#/loggedin',
      response_type:'id_token',
      scope:'openid profile',
      post_logout_redirect_uri:'',
      loadUserInfo: true,
      response_mode: 'query',
      userStore: new WebStorageStateStore({ store: window.localStorage }),
      metadata:{
        issuer: 'https://localhost:44302/',
        authorization_endpoint: 'https://localhost:44302/login'
      }
    };

     this.userManager = new UserManager(settings);
  }

In the above setting I'm using metadata because I was getting .well-known doc not found.

app.routing.module.ts

  {path:'loggedin',component:AuthUserComponent },
login(): Promise<any>{
    return this.userManager.signinRedirect();
  }

completeLogin(): any{
    return this.userManager.signinRedirectCallback();
  }

User will be redirectback to AuthUserComponent after successfull login

auth.user.component.ts

ngOnInit(): void {
    this.authService.completeLogin().then(function (loginCompleted) {
     console.log(loginCompleted);
    });
  }

**ASP.NET OWIN **

Startup.cs

app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                LoginPath = new PathString("/login")
            });
            
            app.UseOpenIdConnectAuthentication(
                            new OpenIdConnectAuthenticationOptions
                            { 
                                ClientId = clientId,
                                Authority = authority,
                                PostLogoutRedirectUri = postLogoutRedirectUri,
                                RedirectUri = redirectUri,
                                Scope = "openid profile email",
                                ResponseType = "id_token",
                                SaveTokens = true,
                                SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                                TokenValidationParameters = new TokenValidationParameters()
                                {
                                    ValidateIssuer = false 
                                },
                                Notifications = new OpenIdConnectAuthenticationNotifications
                                {
                                    RedirectToIdentityProvider = (context) =>
                                    {
                                        context.ProtocolMessage.Prompt = "login";
                                        return Task.FromResult(0);
                                    },
                                    AuthenticationFailed = (context) =>
                                    {
                                        context.HandleResponse();
                                        context.OwinContext.Response.Redirect("/login");
                                        return Task.CompletedTask;
                                    },
                                    SecurityTokenReceived = (context) =>
                                    {
                                        return Task.FromResult(0);
                                    },
                                    SecurityTokenValidated = (context) =>
                                    {
                                     
                                        string idToken = context.ProtocolMessage.IdToken;
                                        Debug.WriteLine(idToken); // Able to retrieve id token here
                                        context.AuthenticationTicket.Identity.AddClaim(new   Claim("id_token", idToken));
                                        return Task.FromResult(0);
                                    }
                                }
                            });

RouteConfig.cs

 public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Auth",
                url: "login",
                defaults: new { controller = "Account", action = "SignIn" }
            );

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }

AccountController.cs

 public ActionResult SignIn()
        {
            redirectUrl = HttpContext.Request.QueryString["redirect_uri"]; // angular redirectUrl
            state = HttpContext.Request.QueryString["state"];
            redirectUrl = redirectUrl + "?state=" + state;
            return View();
        }

        [HttpPost, Route("Account/TrySignIn")]
        public void TrySignIn()
        {
            if (!Request.IsAuthenticated)
            {
                HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = redirectUrl }, 
              OpenIdConnectAuthenticationDefaults.AuthenticationType);
            }
        }

What I have done so far - Please find above chunks of code and configuration.

  1. I am able to redirect to ASP.NET OWIN from Angular for authentication.
  2. Logged in successfully.
  3. Redirected back to Angular app.

Error I'm getting after redirect back to angular

  1. Error: No id_token in response
  2. UserManager.getUser: user not found in storage
  3. No state found - Sometimes

Helpful link - https://www.scottbrady91.com/angular/spa-authentiction-using-openid-connect-angular-cli-and-oidc-client

https://github.com/jmurphzyo/Angular2OidcClient/blob/master/src/app/shared/services/auth.service.ts[Angular2OidcClient][2]

**My requirement - ** In Angular app how to get user details or id_token or both. . Thanks in Advance.

0

There are 0 answers