I create OpenId Provider by DotNetOpenAuth Library.
I use OpenIdProviderMvc project that found on sample of DotNetOpenAuth and customized it.
Now I have 2 question:
How can I remove AskUser step?
How can i signout in provider after response to RP?
Skipping the ask user step is as easy as changing the OpenIdController.ProcessAuthRequest method so that instead of redirecting to the AskUser action, it always (effectively) follows the path as if AutoRespondIfPossible returned true.
You can effectively sign the user out "after" response to RP by clearing the cookie in the same redirect instruction to the browser. So before returning from the ProcessAuthRequest method, try:
FormsAuthentication.SignOut();
If that doesn't work, you may have to do the cookie manipulation yourself as described in this question.
Related
I would like to know that how [Authorize] attribute recognize that this user is authenticate?
If user is valid then we call FormsAuthentication.SetAuthCookie() method and as per MSDN this method:
Creates an authentication ticket for the supplied user name and adds it to the cookies collection of the response, or to the URL if you are using cookieless authentication.
Is [Authorize] attribute checks authentication ticket or cookies collection?
[Authorize] does not deal with any authentication mechanism itself. It merely looks in the users IIdentity for the IsAuthenticated flag. It will also look in the users IsMemberOf method, for authorization based on roles.
All the work to decode the authentication ticket is done in the early stages of the app pipeline, which sets those flags. By the time the Authorization Attribute methods are called, all that work has already been done and is stored in the users runtime data.
You can easily check the source code for the Authorize attribute, and you will see that it's quite simple in nature. It just returns true or false based on some simple lookups.
It's become more complicated in .net core, where it's based on policies and what not, but the original MVC implementation was quite simple.
My answer relates to ASP.NET Core I'm not sure if you asked about classic ASP.NET but this should be similar.
There's a middleware that you have to add for [Authorize] to work. ASP.NET Core provides this middleware out of the box and you can add your custom authentication handlers too.
You can check how it's implemented by reading: https://github.com/aspnet/Security/tree/dev/src
For example you want to use JWT bearer authentication, you have to add JWT bearer middleware, this is simply extension of AuthenticationBuilder: https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerExtensions.cs which calls AddScheme under the hood.
You want to use cookie based authentication you just call AddCookie which is also extension that calls AddScheme under the hood: https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNetCore.Authentication.Cookies/CookieExtensions.cs
Usage of it is documented here: https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x?view=aspnetcore-2.1
See also Using the [Authorize] Attribute
Web API provides a built-in authorization filter, AuthorizeAttribute. This filter checks whether the user is authenticated. If not, it returns HTTP status code 401 (Unauthorized), without invoking the action.
If you are interested how this filter works under the hood you can check it here.
You must be authenticated before you can be authorized, this is the logic responsible for it: https://github.com/aspnet/Security/blob/644f34e90d35b369efdce9c11ab1db42e0a7f4a7/src/Microsoft.AspNetCore.Authorization.Policy/PolicyEvaluator.cs#L91
In summary
how [Authorize] attribute knows that this user is authenticated.
Authorize attribute alone doesn't know if this user is authenticated. This is handled by authentication middleware and depends stricly on the scheme it tries to authenticate with. It simply tries to authenticate with schemes you have added(cookie,jwt etc.) by calling HttpContext.AuthenticateAsync which is simply calling AuthenticationService.AuthenticateAsync under the hood and sets HttpContext.User from the result ClaimsPrincipal, which is simply result from schema handler like jwt handler for instance. I think this should give you more in-depth idea how this works.
Generally if you're starting new project I don't recommend using classic ASP.NET and prepare for the future with .NET Core as everything is now going in this direction. ASP.NET 5 ( I also refer to it as "classic") is pretty much dead now.
Can I make a Single Logout from WSO2 Identity Server using POST not Redirect?
I keep getting the following message:
No established Sessions corresponding to the Session Indexes provided
After some debugging I found out that the session index is obtained by a corresponding sessionID. This session ID is obtained from a cookie named samlssoTOkenId. The thing is that when I am sending a POST to the Identity Provider, I do not have this cookie - I can set it up manually but I do not know its value.
My questions are:
Is this appraoch even possible - using POST not REDIRECT?
Is there some configuration on the Identity Provider which will search for the session index in the request itself not using the cookie approach?
Is it possible to somehow obtain the value of this session ID - when receiving the response after authentication or some other means?
Thanks in advance!
With WSO2IS 4.5.0 and latest versions SessionIndex attribute is returned with the SAML2 Response. Here, You need to enable the Enable Single Logout when service provider is registered in WSO2IS. Also all Single logout requests are handled with respect to the SessionIndex attribute not with the "samlssoTOkenId". As i understood it is invalid to use the cookie values as SessionIndex. But there is no way to configure POST and Redirect. I guess currently it is only supported for Post. Please find the more details about single logout implementation from here. This blog is true with the WSO2IS as well
I would like to understand briefly how the authorize filter and FormAuthentication.SetAuthCookie work under the hood. It's the only thing I find ambiguous after reading some books on the language.
I don't understand how the authorize filter knows where to look. And what about FormsAuthenticationTicket VS FormAuthentication ? And is cookie the most secure way, I mean I'm sure it's possible to export the cookie from a browser and use it somewhere else..?
You might find this question helpful.
If you're interested in how the Authorize filter works in more detail you can review the source code: AuthorizeAttribute
Briefly the Authorize filter will check whether the user has been authenticated by checking the HttpContext.User.Identity.IsAuthenticated property. The User property will have been set by the FormsAuthenticationModule in the case of Forms Authentication.
The FormsAuthentication.SetAuthCookie method creates a ticket for the authenticated user (assuming the user has provided the correct credentials) and adds it to the cookies collection of the response. Alternatively the module can be configured to use cookieless authentication if you want but the encrypted ticket is still sent with each HTTP request. Either way the client (browser) needs a way of telling the server that the requested is authenticated.
Regarding your concerns over security there are some ideas in this question.
I'm implementing and OpenId Provider based on the DotNetOpenAuth OpenIdProviderMVC sample. From the RP, I'm creating an OpenIdRelyingParty, and calling CreateRequest with
http://localhost:PORT/User/xrds
This correctly redirects to the OP, and everything seems to work, but the ClaimedIdentifier that comes back is always
http://localhost:PORT/User/xrds
even when I'm expecting
http://localhost:PORT/user/username
where username is the user I logged in with. Is this an issue with the sample, am I using an incorrect URL as the UserSuppliedIdentifier, or is it something else?
Try to define a different URL as UserSuppliedIdentifier. For instance, use something like http://localhost:PORT/Discovery that executes an action returning the XRDS file. And for identity discovery, define a route to redirect http://localhost:PORT/user/username to a action Identity serving the XRDS file for identity verification.
That worked for me.
Good luck.
In the authentication control I have the following line to mark a user as authenticated in the system (after checking out the password):
FormsAuth.SignIn(userName, rememberMe);
and if I redirect, which is the standard behvaior, everything is ok. But if I show a view right away, the usual ways to check whether a user is authenticated:
Page.User.Identity.IsAuthenticated
Request.IsAuthenticated
don't work. They say the user is not authenticate. How can I make the authentication effective immediately or is there another way to check that would allow me to find out when the user just logged in?
FormsAuth.SignIn is a function which is generated when you create a new ASP.NET MVC project from Visual Studio.
That function simply calls FormsAuthentication.SetAuthCookie, which according to the docs, sets the authentication cookie in the response.
This explains why it works if you redirect (because the client will play back the cookie in the subsequent request), but not right after the call.
Redirecting is the right/conventional way to do this, but if you absolutely insist on checking authentication before a redirect, then you could create an IsAuthenticated flag in session state and refer to that when checking.
On your Controllers, you should be able to use the following to check if they're authenticated.
User.Identity.IsAuthenticated;
I would check to make sure that your AccountController is properly saving the Principal object as you move from page to page.
In addition to using the FormsAuth.Signin or FormsAuthentication.SetAuthCookie, you can also set the User.Identity manually in your sign-in control when the sign-in code executes. As written above, the reason is because the FOrmsAuth.SignIn simply sets the authentication cookie to be picked up next time in the Request_OnAuthenticate event. (Which simply decodes the cookie and sets the HttpContext.User property)