Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IdentityServer4 + ASP.NET core API + Angular: Login/authentication

I'm using IdentityServer4 to handle authentication and authorization in my ASP.NET core API. I use angular4 on client side. I know that I can use token endpoint (http://myapidomain/connect/token) to get access_token by using grantype = ResourceOwnerPassword. It means that I provide username and password in login UI to authenticate.

My question is: do we need to implement API Account/Login anymore? I think that IdentityServer4 is already handle signin via cookie authentication middleware automatically. If we need to implement API Account/Login. What is best practice to implement that. I read somewhere is that use this for login

await  HttpContext.Authentication.SignInAsync(identityUser.Id,                                                                             identityUser.UserName);

and this for logout

await HttpContext.Authentication.SignOutAsync

The second question of mine is: When I get access_token from connect/token. I try to get userinfo by access http://myapidomain/connect/userinfo. But I always get 405 error code. What are my missing

in angular client

authFormHeaders() {
    const header = new Headers();
    header.append('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
    header.append('Accept', 'application/json');
    header.append('Authorization', 'Bearer ' + this.oidcSecurityCommon.getAccessToken());
    return header;
  }

getUserInfo() {
        let self = this;
        let options = new RequestOptions({
            method: RequestMethod.Get,
            headers: this.authService.authFormHeaders()
        });
        return self.http.get(this.authWellKnownEndpoints.userinfoEndpoint, options)
            .map((res: Response) => {
                return res.json();
            })
            .catch(self.appService.handleError);
    }

in my API server side:

CorsPolicyBuilder corsBuilder = new CorsPolicyBuilder()
                .AllowAnyHeader()
                .AllowAnyMethod()
                .AllowAnyOrigin()
                .AllowCredentials();
            services.AddCors(opts =>
            {
                opts.AddPolicy("AllowAllOrigins", corsBuilder.Build());
            });

var url = optionsAccessor.Value.SystemConfig.Authority;
            app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
            {
                Authority = url,
                RequireHttpsMetadata = false,
                ApiName = "netpower.qms.saas.api"/*,
                AllowedScopes = { IdentityServerConstants.StandardScopes.OpenId }*/
            });
app.UseCors("AllowAllOrigins");
like image 581
jack.pop Avatar asked Jul 14 '17 03:07

jack.pop


Video Answer


1 Answers

For Angular client, should you be using grantype Implicit and not ResourceOwnerPassword.The resource owner password credentials grant type is suitable in cases where the resource owner has a trust relationship with the client, such as the device operating system or a highly privileged application. The authorization server should take special care when enabling this grant type and only allow it when other flows are not viable(From OAuth Spec)

The resource owner password grant type allows to request tokens on behalf of a user by sending the user’s name and password to the token endpoint. This is so called “non-interactive” authentication and is generally not recommended. There might be reasons for certain legacy or first-party integration scenarios, where this grant type is useful, but the general recommendation is to use an interactive flow like implicit or hybrid for user authentication instead.

For implementation using Implicit,you can refer this and for using ResourceOwnerpassword ,refer this .

The flow for Resource type is as follows

+----------+
 | Resource |
 |  Owner   |
 |          |
 +----------+
      v
      |    Resource Owner
     (A) Password Credentials
      |
      v
 +---------+                                  +---------------+
 |         |>--(B)---- Resource Owner ------->|               |
 |         |         Password Credentials     | Authorization |
 | Client  |                                  |     Server    |
 |         |<--(C)---- Access Token ---------<|               |
 |         |    (w/ Optional Refresh Token)   |               |
 +---------+                                  +---------------+

For ResourceOwnerPassword type with Angular and Identity Server 4,You can refer this GitHub repo which also contains some sample code for client and server side

The steps are as follows

  1. The resource owner provides the client with its username and password.

  2. The client requests an access token from the authorization server's token endpoint by including the credentials received from the resource owner. When making the request, the client authenticates with the authorization server.

  3. The authorization server authenticates the client and validates the resource owner credentials, and if valid, issues an access token.

do we need to implement API Account/Login anymore?

No you do not have to implement.As you suspected,this is done in the Authorization Server.You will send the user name and password to Identity Server 4 Authentication Server and that will be giving you the Bearer token.And your middleware (app.UseIdentityServerAuthentication) will authenticate the request for your application .

I try to get userinfo by access http://myapidomain/connect/userinfo. But I always get 405 error code. What are my missing

You can look into identity server logs to find out what is missing.I captured a sample requests and it will look like this

POST http://myapidomain/connect/token HTTP/1.1
Host: myapidomain
Proxy-Connection: keep-alive
Content-Length: 142
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/plain, */*
Origin: http://angularspawebapi.azurewebsites.net
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36
Content-Type: application/x-www-form-urlencoded


client_id=AngularSPA&grant_type=password&username=admin%40gmail.com&password=Admin01*&scope=WebAPI%20offline_access%20openid%20profile%20roles


GET http://myapidomain/connect/userinfo HTTP/1.1
Host: myapidomain
Proxy-Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/plain, */*
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjhDRTQ1ODAwQTAwNkExNkZGMzEwOTExMDVCRjNDNTY2MzgzNEUxQkEiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJqT1JZQUtBR29XX3pFSkVRV19QRlpqZzA0Ym8ifQ.eyJuYmYiOjE1MDAwOTk4NjIsImV4cCI6MTUwMDEwMDc2MiwiaXNzIjoiaHR0cDovL2FuZ3VsYXJzcGF3ZWJhcGkuYXp1cmV3ZWJzaXRlcy5uZXQiLCJhdWQiOlsiaHR0cDovL2FuZ3VsYXJzcGF3ZWJhcGkuYXp1cmV3ZWJzaXRlcy5uZXQvcmVzb3VyY2VzIiwiV2ViQVBJIl0sImNsaWVudF9pZCI6IkFuZ3VsYXJTUEEiLCJzdWIiOiI5Y2I1ZGViNS1iZWRmLTRkMWItOThkNS05ZTFjYTgwNzVhYjAiLCJhdXRoX3RpbWUiOjE1MDAwOTk4NjEsImlkcCI6ImxvY2FsIiwicm9sZSI6ImFkbWluaXN0cmF0b3IiLCJzY29wZSI6WyJvcGVuaWQiLCJwcm9maWxlIiwicm9sZXMiLCJXZWJBUEkiLCJvZmZsaW5lX2FjY2VzcyJdLCJhbXIiOlsicHdkIl19.CZAGtK5hvwgkMvX9NQ-8zTFr8Cv3SRVhM-u1WdqdLwI-qbdknfhhVFFHFpPzEWEJnKhsi3aE_BOb_UtRiDBWNHzlXAGmKSjtd70HOlT3dR9Sj_v09Ld15On3HihgfeDwOzIt10ZYwwjRr1tRCf6Ro41FQ2UrzBYcSFe47md7DSlxPXbjnQAHdu8gHMITFF8Nqx0V9OEw21fofRdBalOpvxf1IBhsJwWLyL4bLFYya8jNispK4MnN_tdaS8kxIMZ8iC_IUlhY4XEj5pkDBA9r8ad_Vn5WavO3Lmr4Tew4uBhlFhbE-Qr6EpErAEBVHVtJYs70XXGJJ7QQLoFNmO5M9w
content-type: text/plain
like image 187
Rohith Avatar answered Oct 16 '22 09:10

Rohith