-1

I'm learning angular and I find a problem that I didn't see anywhere else. To the point, when I'm trying to login to my client angular app with oidc-client via identityserver, It's working great up to a point. I'm redirecting to a identityserver, logged in, goes back to the login-callback, in server-side i'm authorized, but if I want to check if I'm authorized in client-side, I got a null user. If i want to logout, I got redirect to sign out in identityserver where I can see my token:
enter image description here

Server-side config.cs:

public class Config
    {
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Email(),
                new IdentityResources.Profile(),
                new IdentityResource("RedDot.API.read", new[] { JwtClaimTypes.Name, JwtClaimTypes.Email, "location" })
            };
        }

        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource("RedDot.API.read", "Resource API")
                {
                    ApiSecrets =
                    {
                        new Secret("secret".Sha256())
                    },

                    UserClaims =
                    {
                        JwtClaimTypes.Name,
                        JwtClaimTypes.Email
                    },
                    Scopes = new List<string> { "RedDot.API.read" }
                }
            };
        }

        public static IEnumerable<Client> GetClients()
        {
            return new[]
            {
                new Client {
                    RequireConsent = false,
                    ClientId = "reddot_ui",
                    ClientName = "RedDot",
                    AllowedGrantTypes = GrantTypes.Code,
                    AllowedScopes = 
                    { 
                        IdentityServerConstants.StandardScopes.OpenId, 
                        IdentityServerConstants.StandardScopes.Profile, 
                        "RedDot.API.read" 
                    },
                    RedirectUris = {"https://localhost:4200/login-callback"},
                    PostLogoutRedirectUris = {"https://localhost:4200/"},
                    AllowedCorsOrigins = {"https://localhost:4200"},
                    AllowAccessTokensViaBrowser = true,
                    AccessTokenLifetime = 3600,
                    ClientSecrets =
                    {
                        new Secret("rwebv832hvegfh49--l-w".Sha256())
                    },
                }
            };
        }
    }

Program.cs:

builder.Services.AddDbContext<AppIdentityDbContext>(options => options.UseSqlServer(dataConnectionString, conf => conf.MigrationsAssembly(assembly)));

builder.Services.AddIdentity<AppUser, IdentityRole>()
     .AddEntityFrameworkStores<AppIdentityDbContext>()
     .AddDefaultTokenProviders();

builder.Services.AddIdentityServer().AddDeveloperSigningCredential()
      .AddOperationalStore(options =>
      {
          options.ConfigureDbContext = builder => builder.UseSqlServer(dataConnectionString, conf => conf.MigrationsAssembly(assembly));
      })
      .AddInMemoryIdentityResources(Config.GetIdentityResources())
      .AddInMemoryApiResources(Config.GetApiResources())
      .AddInMemoryClients(Config.GetClients())
      .AddAspNetIdentity<AppUser>();

Client-side angular config:

private getUserManager() {
        if (!this._userManager) {
          const userManagerSettings: UserManagerSettings =
            new UserManagerSettings();
    
          userManagerSettings.authority = 'https://localhost:5443';
          userManagerSettings.client_id = 'reddot_ui';
          userManagerSettings.response_type = 'code';
          userManagerSettings.scope = 'openid profile RedDot.API.read'; 
          
          userManagerSettings.redirect_uri = 'https://localhost:4200/login-callback';
          userManagerSettings.post_logout_redirect_uri = 'https://localhost:4200/logout-callback';
    
          userManagerSettings.automaticSilentRenew = true;
          userManagerSettings.silent_redirect_uri = 'https://localhost:4200/silent-callback';
    
          userManagerSettings.userStore = new WebStorageStateStore({
            store: window.localStorage,
          }); // store information about Authentication in localStorage
    
          this._userManager = new UserManager(userManagerSettings);
    
          this._userManager.getUser().then((user) => {
            this._user = user;
            this.isUserDefined = true;
          });
        }
    }

Rest of authorize class in angular:

import { Injectable } from "@angular/core";
import { User, UserManager, WebStorageStateStore } from "oidc-client";
import { UserManagerSettings } from "../_models/usermanager.settings";

@Injectable()
export class AuthenticationService {
    isUserDefined = false;
    private _user: User | null;
    private _userManager: UserManager;

    isLoggedIn() {
        return this._user != null && !this._user.expired;
    }

    getName() {
        return this._user?.profile.nickname;
    }

    getAccessToken() {
        return this._user ? this._user.access_token : "";
    }

    getClaims() {
        return this._user?.profile;
    }

    startAuthentication() : Promise<void> {
        this.getUserManager();
        return this._userManager.signinRedirect();
    }

    completeAuthentication() {
        this.getUserManager();
        return this._userManager.signinRedirectCallback().then((user) => {
            this._user = user;
            this.isUserDefined = true;
        });
    }

    startLogout(): Promise<void> {
        this.getUserManager();
        return this._userManager.signoutRedirect();
    }

    completeLogout() {
        this.getUserManager();
        this._user = null;
        return this._userManager.signoutRedirectCallback();
    }


    silentSignInAuthentication() {
        this.getUserManager();
        return this._userManager.signinSilentCallback();
    }
}

Dunno where the problem can be and why I'm not authorized on client-side.

I've tried to change response type and protocol from http to https and conversely with no effect. Maybe somebody had the same problem.

SzymonG27
  • 26
  • 1
  • 6

1 Answers1

1

The code you provided doesn't look like there is anything wrong. According to your description, you can log in and log out successfully, but you are not authorized. Does it mean that you cannot access the corresponding resources? Do you have any error messages?

I used https://demo.duendesoftware.com site to test with Angular application (here is the code of Angular), but did not reproduce your situation. You can see how the configuration items in it perform, and whether your configuration is missing some steps compared to it.

In addition, I found a sample code that is similar to your Angular program, but the Scope configuration is slightly different from yours. I am not sure if this is the reason, but you can use it as a reference

Chen
  • 4,499
  • 1
  • 2
  • 9
  • Hi Chen, thank you very much for your helpful answer. Yes, I can log in and log out successfully, but when I check If user is logged in via function isLoggedIn in AuthenticationService, I got false. The same when I tried to print his username/id etc. I was trying to manipulate scopes. When I did something wrong with scope, I got an Error in IdentityServer `Invalid scope`, but I will try to do otherwise as you said. I tried different response types, used code, implicit and hybrid, didn't work. Thank you for your links and help one more time, I will try something from your submitted materials :) – SzymonG27 Feb 14 '23 at 17:26