首页 > 解决方案 > 用 Angular 组件替换 IdentityServer4 登录页面

问题描述

我想将 IdentityServer4(代码 + PKCE 流)与 .Net Core 和 Angular 一起使用。

我不想使用快速入门 UI,而是希望在 Angular 端进行登录。在官方教程中,用户转到 Angular 应用程序,重定向到 IdentityServer4 UI,在那里登录,然后有另一个重定向 - 返回到 Angular 应用程序。我还想提一下,我没有使用 .net 身份和实体框架,因为数据库流依赖于存储过程。

在我的设置中,Identiy Server 在端口 5555 上运行,Angular App 在端口 4200 上运行。为了与服务器通信,我使用的是 oidc-client-js。

我创建了一个从 Angular 调用的示例端点(登录)。不幸的是,IdSr 没有将我重定向到 AuthCallbackComponent。我只是得到一个空洞的回应(如预期的那样),但没有更多的事情发生。据我了解,在模拟登录用户后,我只需要引发 UserLoginSuccessEvent。之后 IdSr 应该生成令牌并进行重定向。我错过了什么吗?我的方法有问题吗?

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();
}

标签: angularasp.net-coreidentityserver4

解决方案


以最好的方式,是的,您的方法有问题;)

如果遵循 JS 客户端应用程序的当前最佳实践,那么您应该将authorization_code授权类型与公共客户端一起使用(即没有秘密)。用户身份验证将涉及重定向到authorize您的实现中的端点identityserver4(如果不存在会话,则可能会显示登录 UI)。

如果您想在客户端中处理登录 UI,那么这通常会涉及使用ResourceOwnerPassword强烈建议使用的授权类型。看这里:

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

identityserver4但是,如果您愿意,没有什么可以阻止您为您的服务编写一个漂亮的 Angular UI 。只是要小心引入 CSRF 问题。

无论哪种方式,都无需创建任何自定义 API 端点来促进登录过程 -authorizetokenOIDCuserinfo端点已经涵盖了。


推荐阅读