c# - JWT and Web API (JwtAuthForWebAPI?) - Looking For An Example -
i've got web api project fronted angular, , want secure using jwt token. i've got user/pass validation happening, think need implement jwt part.
i believe i've settled on jwtauthforwebapi example using great.
i assume method not decorated [authorize] behave does, , method decorated [authorize] 401 if token passed client doesn't match.
what can't yet figure out how send token client upon initial authentication.
i'm trying use magic string begin, have code:
registerroutes(globalconfiguration.configuration.routes); var builder = new securitytokenbuilder(); var jwthandler = new jwtauthenticationmessagehandler { allowedaudience = "http://xxxx.com", issuer = "corp", signingtoken = builder.createfromkey(convert.tobase64string(new byte[]{4,2,2,6})) }; globalconfiguration.configuration.messagehandlers.add(jwthandler);
but i'm not sure how gets client initially. think understand how handle on client, bonus points if can show angular side of interaction.
i ended-up having take information several different places create solution works me (in reality, beginnings of production viable solution - works!)
i got rid of jwtauthforwebapi (though did borrow 1 piece allow requests no authorization header flow through webapi controller methods not guarded [authorize]).
instead i'm using microsoft's jwt library (json web token handler microsoft .net framework - nuget).
in authentication method, after doing actual authentication, create string version of token , pass along authenticated name (the same username passed me, in case) , role which, in reality, derived during authentication.
here's method:
[httppost] public loginresult postsignin([frombody] credentials credentials) { var auth = new loginresult() { authenticated = false }; if (trylogon(credentials.username, credentials.password)) { var tokendescriptor = new securitytokendescriptor { subject = new claimsidentity(new[] { new claim(claimtypes.name, credentials.username), new claim(claimtypes.role, "admin") }), appliestoaddress = configurationmanager.appsettings["jwtallowedaudience"], tokenissuername = configurationmanager.appsettings["jwtvalidissuer"], signingcredentials = new signingcredentials(new inmemorysymmetricsecuritykey(jwttokenvalidationhandler.symmetrickey), "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256", "http://www.w3.org/2001/04/xmlenc#sha256") }; var tokenhandler = new jwtsecuritytokenhandler(); var token = tokenhandler.createtoken(tokendescriptor); var tokenstring = tokenhandler.writetoken(token); auth.token = tokenstring; auth.authenticated = true; } return auth; }
update
there question handling token on subsequent requests. did create delegatinghandler try , read/decode token, create principal , set thread.currentprincipal , httpcontext.current.user (you need set both). finally, decorate controller methods appropriate access restrictions.
here's meat of delegatinghandler:
private static bool tryretrievetoken(httprequestmessage request, out string token) { token = null; ienumerable<string> authzheaders; if (!request.headers.trygetvalues("authorization", out authzheaders) || authzheaders.count() > 1) { return false; } var bearertoken = authzheaders.elementat(0); token = bearertoken.startswith("bearer ") ? bearertoken.substring(7) : bearertoken; return true; } protected override task<httpresponsemessage> sendasync(httprequestmessage request, cancellationtoken cancellationtoken) { httpstatuscode statuscode; string token; var authheader = request.headers.authorization; if (authheader == null) { // missing authorization header return base.sendasync(request, cancellationtoken); } if (!tryretrievetoken(request, out token)) { statuscode = httpstatuscode.unauthorized; return task<httpresponsemessage>.factory.startnew(() => new httpresponsemessage(statuscode)); } try { jwtsecuritytokenhandler tokenhandler = new jwtsecuritytokenhandler(); tokenvalidationparameters validationparameters = new tokenvalidationparameters() { allowedaudience = configurationmanager.appsettings["jwtallowedaudience"], validissuer = configurationmanager.appsettings["jwtvalidissuer"], signingtoken = new binarysecretsecuritytoken(symmetrickey) }; iprincipal principal = tokenhandler.validatetoken(token, validationparameters); thread.currentprincipal = principal; httpcontext.current.user = principal; return base.sendasync(request, cancellationtoken); } catch (securitytokenvalidationexception e) { statuscode = httpstatuscode.unauthorized; } catch (exception) { statuscode = httpstatuscode.internalservererror; } return task<httpresponsemessage>.factory.startnew(() => new httpresponsemessage(statuscode)); }
don't forget add messagehandlers pipeline:
public static void start() { globalconfiguration.configuration.messagehandlers.add(new jwttokenvalidationhandler()); }
finally, decorate controller methods:
[authorize(roles = "onerolehere")] [get("/api/admin/settings/product/allorgs")] [httpget] public list<org> getallorganizations() { return queryabledependencies.getmergedorganizations().tolist(); } [authorize(roles = "adifferentrolehere")] [get("/api/admin/settings/product/allorgswithapproval")] [httpget] public list<approvableorg> getallorganizationswithapproval() { return queryabledependencies.getmergedorganizationswithapproval().tolist(); }
Comments
Post a Comment