rook
rook

Reputation: 3008

Angular 2 & dotnet core integrated windows authentication

I have a simple setup. Angular2 client and dotnet core webapi server. Mandatory windows auth, so no login/registration pages. On the client side I need to know if the current user has specific privileges. Let's say he can be a User, a Power User or an Admin. Those roles must be assigned via Active Directory (member of a specific group? something else?). The question is how on the client side can I get user's role(s)?

So far the first request (for index.html) looks like this:

Request URL:http://localhost:5000/
Request Method:GET
Status Code:200 OK
Remote Address:[::1]:5000

Response Headers:
Accept-Ranges:bytes
Access-Control-Allow-Origin:*
Content-Encoding:gzip
Content-Type:text/html
Date:Sat, 11 Mar 2017 23:00:17 GMT
ETag:"1d29abb3a9b8e62"
Last-Modified:Sat, 11 Mar 2017 23:00:08 GMT
Persistent-Auth:true
Server:Kestrel
Transfer-Encoding:chunked
Vary:Accept-Encoding
WWW-Authenticate:Negotiate oRswGaADCgEAoxIEEAEAAAAgBHIw6Z3ltQAAAAA=
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?QzpcUHJvamVjdHNcSGxyXFplbml0aFxaZW5pdGguV2Vi?=
X-StackifyID:V1|a92d413d-a6f2-41f5-82d4-d561bcfb7ea4|

Request Headers:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8
Authorization:Negotiate oXcwdaADCgEBoloEWE5UTE1TU1AAAwAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAABXCiOIKADk4AAAAD2dOupNeJw531jZD2IvezcmjEgQQAQAAAF0+6pxdYvmTAAAAAA==
Cache-Control:no-cache
Connection:keep-alive
Cookie:_ga=GA1.1.1850763475.1487368913
Host:localhost:5000
Pragma:no-cache
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36

The second one:

Request URL:http://localhost:5000/inline.bundle.js
Request Method:GET
Status Code:200 OK
Remote Address:[::1]:5000

Response Headers:
Accept-Ranges:bytes
Access-Control-Allow-Origin:*
Content-Encoding:gzip
Content-Type:application/javascript
Date:Sat, 11 Mar 2017 23:00:18 GMT
ETag:"1d29abb3a9b9a84"
Last-Modified:Sat, 11 Mar 2017 23:00:08 GMT
Persistent-Auth:true
Server:Kestrel
Transfer-Encoding:chunked
Vary:Accept-Encoding
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?QzpcUHJvamVjdHNcSGxyXFplbml0aFxaZW5pdGguV2ViXGlubGluZS5idW5kbGUuanM=?=
X-StackifyID:V1|9ab31082-9a9d-4513-8e8c-ae83e8163117|

Request Headers:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Cookie:_ga=GA1.1.1850763475.1487368913
Host:localhost:5000
Pragma:no-cache
Referer:http://localhost:5000/
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36

And the one for webapi:

Request URL:http://localhost:5000/mymethod
Request Method:GET
Status Code:200 OK
Remote Address:[::1]:5000

Response Headers:
Access-Control-Allow-Origin:*
Content-Type:application/json; charset=utf-8
Date:Sat, 11 Mar 2017 23:00:19 GMT
Persistent-Auth:true
Server:Kestrel
Transfer-Encoding:chunked
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?QzpcUHJvamVjdHNcSGxyXFplbml0aFxaZW5pdGguV2ViXGFwaVxjb25maWd1cmF0aW9uXHZlcnNpb24=?=
X-StackifyID:V1|0f198f5d-a0fe-4e6c-974a-bd31f0d32ec6|

Request Headers:
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Cookie:_ga=GA1.1.1850763475.1487368913
Host:localhost:5000
Pragma:no-cache
Referer:http://localhost:5000/
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36

What approach can I take to get user permissions (and keep them on the client side through...) and using them for route guards?

It can also be that the page makes several webapi calls during loading. Do I authorize the user every call or somehow use previous call result?

Thank you.

Upvotes: 0

Views: 2579

Answers (2)

yanbu
yanbu

Reputation: 183

If you really want to use AD groups as your authorization you will want to set up a permissions service which queries AD through a webapi method, and use a hot observable to disseminate permissions without having to constantly re-query AD.

In your webapi method:

public List<string> GetUserPermissions(){
    List<string> permissionsList = new List<string>();
    if (User.IsInRole("PowerUsers")){
        permissionsList.Add("PowerUsers");
    }
    if (User.IsInRole("Admin")) {
        permissionsList.Add("Admin");
    }
    if (User.IsInRole("User")) {
        permissionsList.Add("User");
    }
    return permissionsList;
}

Basically, you will want to do something along the lines of the below in your permission service:

permissions: any[] = [];

initPermissions(): void {
    this.getPermissions().subscribe(perms => this.permissions = perms);
}

getPermissions(): Observable<any> {
    return this.http.get(`${this.baseUrl}/api/Permissions/GetUserPermissions`)
             .publishLast().refCount();
}

isInRole(roleName: string): boolean{
    return this.permissions.some(perm => perm === roleName);
}

In your app.component ngInit() call the initPermissions() method from your service.

Then you will need to import the permissions service into the components you want to use it in, create the permissions in the constructor private permissions: permissionsService and you can do cool stuff like *ngIf="permissions.isInRole('Admin')" to hide features and use inside auth guards and whatnot. You'll probably still want to use authorization decorators on your web api methods to secure your data however.

Note that the above is NOT my actual permissions code, so you may have to debug it to get it to work. You'll probably want to improve upon it as well, it is merely to give you some ideas.

Upvotes: 1

Matteo Conta
Matteo Conta

Reputation: 1449

I think this article is a great starting point for angularjs & Integrated windows authentication.

CodeProject : AngularJS-Web-API-Active-Directory-Security

Regarding your second question you can use an encrypted token with user name, roles, expiration time and, on every request, decrypt this token server side and use it server side.

You can also renew the token on every request and resend it to the client in order to update his session information.

Upvotes: 1

Related Questions