Tez Wingfield
Tez Wingfield

Reputation: 2251

Retrieving/Reading Claim Values from ClaimsPrincipal

If I get straight into it, I've built a RESTful Service (WebAPI V2) with basic authentication... All is working as expected but I'm very unsure on how to retrieve values from ClaimsPrincipal. I've read many articles but all point to using third party libraries And/or Identity in .Net.

To keep it short and sweet, I have an Attribute performing necessary logic and a custom authenticateService which points to my data store.

I have an n-tier architecture:

  1. API
  2. Service
  3. Business
  4. Data

So I guess the first question is, how can I read the values from ClaimsPrincipal? (Apologies first time using Claims)

To Note: I'm expecting this to fire on each request, there will be no session.

Some logic that creates and authenticates the user (Inside Attribute)

using (var authService = new AuthenticateService())
            {
                var client = await _authenticateService.AuthenticateAsync(
                    apiKey,
                    password);

                if (client != null)
                {
                    // Create a ClaimsIdentity with all the claims for this user.
                    Claim apiKeyClaim = new Claim("API Key", apiKey);
                    Claim clientNameClaim = new Claim(ClaimTypes.Name, client.ClientName);
                    Claim clientKeyClaim = new Claim("Client Key", client.ClientKey);

                    List<Claim> claims = new List<Claim>
                    {
                        apiKeyClaim,
                        clientNameClaim,
                        clientKeyClaim
                    };

                    // important to set the identity this way, otherwise IsAuthenticated will be false
                    // see: http://leastprivilege.com/2012/09/24/claimsidentity-isauthenticated-and-authenticationtype-in-net-4-5/
                    ClaimsIdentity identity = new ClaimsIdentity(claims, "Basic");
                    // AuthenticationTypes.Basic

                    var principal = new ClaimsPrincipal(identity);
                    return principal;

                    //var principal = new GenericPrincipal(new GenericIdentity("CustomIdentification"),
                    //                   new[] { "SystemUser" });

                    //return principal;
                }
                else
                {
                    return null;
                }
            }

Accessing Claim Values in my API controller:

[IdentityBasicAuthentication]
    [Authorize]
    [RoutePrefix("api")]
    public class OrderController : ApiController
    {
        private IOrderService _orderService;
        public OrderController(IOrderService orderService)
        {
            _orderService = orderService;
        }
        // POST api/<controller>
        [HttpPost]
        [Route("order")]
        public async Task<IHttpActionResult> Post([FromBody]Models.Model.Order order)
        {

            var modelResponse = new ModelResponse<Models.Model.Order>(order);
            if (order == null)
                return BadRequest("Unusable resource.");

            if (!modelResponse.IsModelValid())
                return this.PropertiesRequired(modelResponse.ModelErrors());

            try
            {
                //Create abstracted Identity model to pass around layers
                // Access Claim values here
                //OR can I use Claims in other layers without creating an abstracted model to pass through.
                await _orderService.AddAsync(order);
            }
            catch (System.Exception ex)
            {
                return InternalServerError();
            }
            finally
            {
                _orderService.Dispose();
            }

            return Ok("Order Successfully Processed.");
        }
    }

Really appreciate your time reading this, hopefully "someone" can direct/help me reading claim values and/or best approach to passing around layers.

Regards,

Upvotes: 11

Views: 38328

Answers (5)

Ilias.P
Ilias.P

Reputation: 199

For those wondering how to get the subject id from a ClaimsPrincipal in .net7 aspcore, it can be done as easily as this

var claim = principal.FindFirst(Claims.Subject); 

var id = Guid.Parse(claim?.Value ?? ""); // or cast/parse it to the expected type

Upvotes: 1

IdusOrtus
IdusOrtus

Reputation: 1116

Useful to view all permissions & claims in Azure Functions v3 (netcore3.1). Clobbered together from various SO articles.

...
using System.Security.Claims;
using System.Linq;
...
[FunctionName("AdminOnly")]
public static async Task<IActionResult> RunAdminOnly(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "test")] HttpRequest req,
ILogger log,
ClaimsPrincipal claimsID)
{
    string perms ="";
    foreach(var h in req.Headers)
    {
        perms += $"{h.Key}:{String.Join(",", h.Value)}" + "\n";
    }

    string claims = "";
    foreach (Claim claim in claimsID.Claims)
    {
        claims += $"{claim.Type} : {claim.Value} \n";
    }

    string claimDetail = "";
    Claim? appRole = claimsID.Claims.FirstOrDefault(c => c.Type == "extension_AppRole"); // custom claim

    claimDetail += appRole?.Value.ToString();

    return new OkObjectResult(perms + "\n\n" + claims + "\n\n" + claimDetail);
}

Upvotes: 0

pranav aggarwal
pranav aggarwal

Reputation: 217

@User.Claims.FirstOrDefault(c => c.Type == "Currency").Value

Upvotes: 11

Ozan BAYRAM
Ozan BAYRAM

Reputation: 2901

I prefer LINQ to access Can be found here: https://msdn.microsoft.com/en-us/library/ee517271.aspx?f=255&MSPPError=-2147217396

Upvotes: 0

HeCtOr
HeCtOr

Reputation: 311

You can access to claims this way. In your controller method:

try 
{
    // ...
    var claimsIdentity = (ClaimsIdentity)this.RequestContext.Principal.Identity;
    foreach(var claim in claimsIdentity.Claims)
    {
        // claim.value;
        // claim.Type
    }
    // ...
}

Upvotes: 15

Related Questions