简体   繁体   中英

Replace IdentityServer4 Login Page with Angular component

I want to use IdentityServer4 (Code + PKCE flow) with .Net Core and Angular.

Instead of using Quickstart UI I want to have log in process on Angular side. In the official tutorial a user goes to Angular app, gets redirect to IdentityServer4 UI, log in there and then there's another redirect - back to Angular app. I also want to mention that I'm not using .net identity and entity framework, since database flow relies on stored procedures.

In my setup I've got Identiy Server running on port 5555 and Angular App running on port 4200. To communicate with the Server I'm using oidc-client-js.

I've created a sample endpoint (Login) that I call from Angular. Unfortunately IdSr doesn't redirect my to the AuthCallbackComponent. I just get an empty response (as expected) but nothing more is happening. As I understand it, after mocking logging the user I just need to raise the UserLoginSuccessEvent. After that IdSr should generate the token and make a redirect. Am I missing something? Is there something wrong in my approach?

export class AuthService {
  private userManager: UserManager;
  private user: User;

  constructor(private client: HttpClient) {
    this.userManager = new UserManager(AuthSettings.settings);
    this.userManager.getUser().then(user => (this.user = user));
  }

  login() {
    let api = "http://localhost:5555/api/User";
    let headers = new HttpHeaders();
    headers.set("Content-Type", "application/json");
    let content = {
      UserName: "test@test.com",
      Id: "123456",
      Name: "Test User"
    };
    let data = `"${content}"`;
    console.log("logging");
    this.client
      .post(api, content, {
        headers: headers,
        withCredentials: false
      })
      .subscribe(response => console.log(response), err => console.log(err));
  }

  async completeAuthentication() {
    this.user = await this.userManager.signinRedirectCallback();
  }
}



import { UserManagerSettings } from "oidc-client";

export class AuthSettings {
  public static settings: UserManagerSettings = {
    authority: "http://localhost:5555/",
    client_id: "ng",
    redirect_uri: "http://localhost:4200/callback",
    post_logout_redirect_uri: "http://localhost:4200/",
    response_type: "code",
    scope: "openid profile email API"
  };
}


export class AuthCallbackComponent implements OnInit {
  constructor(private authService: AuthService) {}

  ngOnInit() {
    this.authService
      .completeAuthentication()
      .then(e => console.log("auth completed"));
  }
}


public static IEnumerable < Client > GetClients() {
    return new List < Client > {
        new Client {
            ClientId = "ng",
            ClientName = "Angular",
            AllowedScopes = {
                "openid",
                "profile",
                "email",
                "API"
            },
            RedirectUris = new List < string > {
                "http://localhost:4200/callback"
            },
            PostLogoutRedirectUris = new List < string > {
                "http://localhost:4200/"
            },
            AllowedCorsOrigins = new List < string > {
                "http://localhost:4200"
            },
            AllowedGrantTypes = GrantTypes.Code,
            RequirePkce = true,
            RequireClientSecret = false,
            AllowAccessTokensViaBrowser = true,
            RequireConsent = false
        }
    };
}


[AllowAnonymous][HttpPost]
public async Task < ActionResult > Login(LoginInputModel model) {
    var user = new User("test@test.com", "123456", "Test User");
    await _eventService.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.Name));
    return Ok();
}

In the nicest possible way, yes there's something wrong with your approach ;)

If following current best practice for JS client side apps then you should be using the authorization_code grant type with a public client (ie no secret). User authentication will involve a redirect to the authorize endpoint in your identityserver4 implementation (which may in turn present a login UI if no session exists).

If you want to handle the login UI in your client then this would typically involve using the ResourceOwnerPassword grant type which is strongly discouraged. See here:

https://www.scottbrady91.com/OAuth/Why-the-Resource-Owner-Password-Credentials-Grant-Type-is-not-Authentication-nor-Suitable-for-Modern-Applications

However there's nothing to stop you from writing a nice whizzy Angular UI for your identityserver4 service should you wish. Just be wary of introducing CSRF issues.

Either way, there's no need to create any custom API endpoints to facilitate the sign in process - the authorize , token and userinfo OIDC endpoints have you covered.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM