i have asp.net mvc 4 application, in i'm trying implement claims-based authentication , authorization. have sso proxy inserts info user (such username) in header. have implemented own claimsauthenticationmanager, , want take username header, create claimsprinsipal containing username claim, pass claimsauthenticationmanager, hit database figure out roles user should have, , populate principal role claims. want use transformed claim rest of user's session.
what have far:
web.config:
<configuration> ... <system.web> ... <authentication mode="forms"> <forms loginurl="~/account/authorize" timeout="20" /> </authentication> </system.web> </configuration>
myclaimstransformer.cs
public class myclaimstransformer : claimsauthenticationmanager { private readonly iauthenticationuow _authenticationuow; private readonly iwebserviceurls _webserviceurls; public myclaimstransformer(iauthenticationuow authenticationuow, iwebserviceurls webserviceurls) { _authenticationuow = authenticationuow; _webserviceurls = webserviceurls; } public override claimsprincipal authenticate(string resourcename, claimsprincipal incomingprincipal) { if (incomingprincipal == null || incomingprincipal.identity == null || !incomingprincipal.identity.isauthenticated) throw new securityexception("no claims principal or not authenticated"); var username = incomingprincipal.identity.name; if (string.isnullorwhitespace(username)) throw new securityexception("no user name found"); // add role claims return incomingprincipal; } }
global.asax.cs
public class mvcapplication : system.web.httpapplication { protected void application_start() { arearegistration.registerallareas(); webapiconfig.register(globalconfiguration.configuration); filterconfig.registerglobalfilters(globalfilters.filters); routeconfig.registerroutes(routetable.routes); bundleconfig.registerbundles(bundletable.bundles); federatedauthentication.federationconfigurationcreated += federatedauthentication_federationconfigurationcreated; } private void federatedauthentication_federationconfigurationcreated(object sender, system.identitymodel.services.configuration.federationconfigurationcreatedeventargs e) { webserviceurls serviceurls = new webserviceurls(); appproperties appproperties = new appproperties(); serviceurls.usernamewebserviceurl = appproperties.usernamewebserviceurl; serviceurls.pointofcontactwebserviceurl = appproperties.pointofcontactwebserviceurl; e.federationconfiguration.identityconfiguration.claimsauthenticationmanager = objectfactory.with<iwebserviceurls>(serviceurls).getinstance<myclaimstransformer>(); } }
accountcontroller.cs
[authorize] public class accountcontroller : basecontroller { [allowanonymous] public actionresult authorize(string returnurl) { string userid = request.headers["userid"]; if (url.islocalurl(returnurl)) { var claims = new list<claim> { new claim(claimtypes.name, userid) }; var id = new claimsidentity(claims, "custom", claimtypes.name, claimtypes.role); var principal = new claimsprincipal(id); // call out registered claimsauthenticationmanager var claimsauthmanager = federatedauthentication.federationconfiguration.identityconfiguration.claimsauthenticationmanager; // set transformed principal var url = request.url; if (url != null) { var newprincipal = claimsauthmanager.authenticate(url.absolutepath, principal); setsessioncookie(newprincipal); thread.currentprincipal = newprincipal; } return redirect(returnurl); } throw new invaliddataexception("bad url"); } private void setsessioncookie(claimsprincipal incomingprincipal) { sessionsecuritytoken token = new sessionsecuritytoken(incomingprincipal); federatedauthentication.sessionauthenticationmodule.writesessiontokentocookie(token); } }
this code runs fine, , when thread.currentprincipal = newprincipal;
line gets executed, proper claims in principal. when use custom claimsauthorizationmanager check claims, none of them there (also, principal no longer authenticated). re-directs accountcontroller authenticate again.
what missing?
in authenticate override, should route incomingprincipal through base claimsauthenticationmanager:
return base.authenticate(resourcename, incomingprincipal);
Comments
Post a Comment