Sunday, October 18, 2020

[.NET core] AddPolicy to Authorize on MVC controller

Sometimes when you are using C# identity, the [Authorize] attribute is not enough,for example, you want additional check not only claims or role, then you can try add policy to make it. 

In this example, we assume a part of method need check token in user claims before access, here is how to implement it. 

1.add a AuthorizationHandler for your policy 
namespace Example.Handler
    // Custom AuthorizationHandler for check token in claim
    public class AuthorizeTokenHandler : AuthorizationHandler<TokenRequirement>
        private readonly AuthService _auth;

        public AuthorizeTokenHandler(AuthService auth)
            _auth = auth;
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TokenRequirement requirement)
            //no token claim
            if (!context.User.HasClaim(x => x.Type == "Token"))
                return Task.CompletedTask;

            var username = context.User.FindFirst(ClaimTypes.Name).Value;
            var token = context.User.FindFirst("Token").Value;

            #region check token
            if (_auth.CheckToken(username,token))

            return Task.CompletedTask;

    public class TokenRequirement : IAuthorizationRequirement

2. add to startup, in ConfigureServices

            services.AddSingleton<IAuthorizationHandler, AuthorizeTokenHandler>();
            //add policy
            services.AddAuthorization(options =>
                options.AddPolicy("TokenRequire", policy =>
                    policy.Requirements.Add(new TokenRequirement()));

3. apply policy to Authorize when you need

[Authorize(Policy = "TokenRequire")]
public ApiResult SomeMethod()

That's all, enjoy it.

Sunday, October 11, 2020

[C#] Best Practices of Get Claim from Identity

If you are using ASP.NET Identity, whatever using ASP.NET Core Identy or ASP.NET Identity, usually you will add some claims into the identity and use it later, but I saw lot people using unsafe way to get claim value from identity, it may cause uncatch error if the claim type not exists, let's see the code.
//set some claims first
var claims = new List<Claim>
     new Claim(ClaimTypes.Name,"test name"),
     new Claim("Token","token123"),
     new Claim("Number","3")
     //new Claim("dummy","dummy string")
var ci = new ClaimsIdentity(claims);

//most seen way, throw error if not exists
var name = ci.Claims.First(x => x.Type == ClaimTypes.Name).Value;
var token = ci.Claims.First(x => x.Type == "Token").Value;  
//using FirstOrDefault() only, throw error if not exists
//var dunno = ci.Claims.FirstOrDefault(x => x.Type == "dunno").Value;

Using this way is easy, but if the claim not exists, if will cause error, whatever you are using First() or FirstOrDefault(). If want to using FirstOrDefault() to get claim value, you can using this fixed way.

            //fixed FirstOrDefault way: return null if not exists
            var dunno = ci.Claims.Where(x => x.Type == "dunno").Select(x => x.Value).FirstOrDefault();

but you can use HasClaim method to check claim exist first, and give a proper value if it not exists.

            //safe way: using HasClaim to check
            var dummy = ci.HasClaim(x => x.Type == "dummy")
                ? ci.Claims.First(x => x.Type == "dummy").Value
                : null;

or you can choose this short way by using FindFirst method.

            //short way: using FindFirst
            var dummyShort = ci.FindFirst("dummy")?.Value;
            //short way for int
            int.TryParse(ci.FindFirst("Number")?.Value, out var number);

I think use ClaimsIdentity.FindFirst Method is the best practices for get claim value.
You can test those here in here

Tuesday, June 2, 2020



以下資料來源翻譯自Yellowstone Bear World


Myth #1: Bears have bad eyesight


Bears actually have excellent eyesight.

就像您家的狗或貓一樣,熊擁有出色的夜視能力。 牠們的眼睛後部有一個稱為脈絡膜層(Tapetum lucidum)的反射膜,該膜可反射光,並使光敏細胞對光進行第二次反應,從而極大地增強了他們在夜間的視力。


因此,別被騙了...那些熊可能會在您見到牠們之前先見到您! (有關資訊請參見Sylvia Dolson的《熊學 Bear-ology》)