Adding multiple values ​​to 1 user request using JSON string

I use the main .net application when I authenticate the user. In our system, the user has several permissions (maybe up to 70).

Now, instead of querying the database for each query, the user makes you think that it would be good to store permissions as a claim. I tried to store each permission as a separate requirement, but even getting up to 10 permissions greatly increases the size of the token.

So, instead of adding 1 application for 1 permit, I wondered if it would change if I added all permissions for 1 application, and this would happen. It keeps the token size small, but I have the necessary permissions.

Now for this, I had to convert all my permissions from the array to a JSON string, and then save them as a claim. To get the request, I can then deserialize the string back to the array, and I will not query the database at all.

Can this be done, or is it a very bad practice? Am I making a ticking time bomb and it will explode soon after doing this?

Sample code here

var identity = new ClaimsIdentity(context.Options.AuthenticationType); identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); // get user permissions var permissions = await _permissionService.GetAllAsync(user); // create list of all permissions List<object> claimPermissions = new List<object>(); foreach (var item in permissions) { claimPermissions.Add(new { Action = item.Action, Type = item.Type }); } // convert list to json var json = Newtonsoft.Json.JsonConvert.SerializeObject(claimPermissions); // add claim identity.AddClaim(new Claim("Permissions", json)); 
+5
source share
1 answer

There is a standard list of most common ClaimTypes types in the System.Security.Claims.ClaimTypes class and I suggest you add them as separate claims. After that, all other claims can be added as soon as UserData. I'm not sure why your application has up to 70 permissions? When you design your infrastructure, it is wise to use best practices that should use role-based authorization. I make it all easier. And remember that these are tried and tested methods. Windows Azure Active Directory has the same design, and yet it can handle any authentication and authorization scenario.

If you need more information on how you can use Json Web Tokens to implement such an authentication mechanism, see my article on this subject here .

Given Jwt, here is how you can check if a user has permissions.

  private static ClaimsPrincipal ValidateToken(string token, string secret, bool checkExpiration) { var jsonSerializer = new JavaScriptSerializer(); var payloadJson = JsonWebToken.Decode(token, secret); var payloadData = jsonSerializer.Deserialize<Dictionary<string, object>>(payloadJson); object exp; if (payloadData != null && (checkExpiration && payloadData.TryGetValue("exp", out exp))) { var validTo = FromUnixTime(long.Parse(exp.ToString())); if (DateTime.Compare(validTo, DateTime.UtcNow) <= 0) { throw new Exception( string.Format("Token is expired. Expiration: '{0}'. Current: '{1}'", validTo, DateTime.UtcNow)); } } var subject = new ClaimsIdentity("Federation", ClaimTypes.Name, ClaimTypes.Role); var claims = new List<Claim>(); if (payloadData != null) foreach (var pair in payloadData) { var claimType = pair.Key; var source = pair.Value as ArrayList; if (source != null) { claims.AddRange(from object item in source select new Claim(claimType, item.ToString(), ClaimValueTypes.String)); continue; } switch (pair.Key) { case "name": claims.Add(new Claim(ClaimTypes.Name, pair.Value.ToString(), ClaimValueTypes.String)); break; case "surname": claims.Add(new Claim(ClaimTypes.Surname, pair.Value.ToString(), ClaimValueTypes.String)); break; case "email": claims.Add(new Claim(ClaimTypes.Email, pair.Value.ToString(), ClaimValueTypes.Email)); break; case "role": claims.Add(new Claim(ClaimTypes.Role, pair.Value.ToString(), ClaimValueTypes.String)); break; case "userId": claims.Add(new Claim(ClaimTypes.UserData, pair.Value.ToString(), ClaimValueTypes.Integer)); break; default: claims.Add(new Claim(claimType, pair.Value.ToString(), ClaimValueTypes.String)); break; } } subject.AddClaims(claims); return new ClaimsPrincipal(subject); } 

I hope this helps

thanks

Stewart

0
source

Source: https://habr.com/ru/post/1207366/


All Articles