How to sign-in to WIF federation on the same page? - asp.net

I have this scenario.
RP with passive federation to 2.
Custom STS for user/password authentication
Everything is working fine. So far the user would press login link, which would go to a restricted area, thus the federation security was triggered, and login screen appeared. It would prompt him to write the credentials, the request was then processed, etc.
Now I'm required to create login (user/password) text-boxes on the same page (default page). How can I achieve federation sign-in operation without redirecting to a login page? Should (or can) I use FederatedPassiveSignIn control? If so, how?

You could show the login boxes on the unprotected landing page if IsAutheticated is false and then send a message to the custom STS login page with the credentials encrypted or whatever which then logs in behind the scenes and redirects back to your app. with the token in the normal manner.
However, if the user is not authenticated and bookmarks a page behind the landing page, they'll be redirected to the STS.

For anyone interested (I doubt someone actually is), I've solved it through - basically - simulating what login page does.
// makes credentials validation, and creates IClaimsPrincipal with the acquired claims
IClaimsPrincipal principal = LoginHelper.SignIn(editEmail.Value, editPassword.Value);
// retrieves the instance of the STS (in this case my custom STS)
TrustedSecurityTokenService service = (TrustedSecurityTokenService) TrustedSecurityTokenServiceConfiguration.Current.CreateSecurityTokenService();
// creates the request manually to point to my original page (or whatever page you desire)
SignInRequestMessage request = FederatedAuthentication.WSFederationAuthenticationModule.CreateSignInRequest(Guid.NewGuid().ToString(), "http://page/i/want/to/go/after/the/validation.aspx", true);
// processes first the request...
SignInResponseMessage response = FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest(request, principal, service);
// ...then the response is processed, and redirected to URL above
FederatedPassiveSecurityTokenServiceOperations.ProcessSignInResponse(response, Response);
This created cookies, and principal is not IsAuthenticated. As if it were process by login page (at least it seems to work so far as expected).

Related

Sending a server side POST from a java webapp

I'm working on a spring-mvc based java app at the moment.
One of the features of this app is that the user can change their email address to another email address.
When the user changes their email address, current state functionality is to log the user out in the same operation, which is achieved by returning
redirect:/j_spring_security_logout
from the controller method that updates the users email address.
New webapp functionality is to only support POST (not GET) for logout, which causes the current functionality of logging out the user on email address change to break.
What is the suggested way around this?
Can I:
a) Send a POST somehow from the server side to log the user out?
b) Logout the user server side somehow (invalidate their session, clear their cookies, and redirect them to the login page?)?
c) Should the user be being logged out on email address change in any case or is this a strange thing to do?
Any advice is more than appreciated.
When using Spring Security with a Servlet 3.0 (or higher) capable container it integrates with the HttpServletRequest.logout method. When calling this method it will trigger the registered Spring Security LogoutHandler. Afterwards you can redirect to the page you want.
#RequestMapping
public String yourMethod(HttpServletRequest request) {
// your logic here
request.logout(); // Logout to force a re-login
return "redirect:/login"; // redirect to page you want
}

Transparent Single Sign On within Identity Server

Following scenario: I'm successfully authenticated in application A, token and cookie is issued. Later I go to the application B. Application B is ASP.NET MVC application. Now when I click the Login button I'm, as expected, successfully logged-in without redirection to the Login page. But I would like to be logged-in without to click on Login button. So when I come to the home page the button shows "Logout", but do not redirect anywhere when I'm not authenticated, until I click on the "Login" button. Now I'm using standard OWIN Middleware and Authorize Attribute. What is the proper way and alternatives to achieve this? Need I write own Authorize Attribut filter?
From the 2nd app you can trigger a "silent" login attempt via an iframe passing prompt=none in the authorization request. If the user is already logged in, then they will get a response immediately (success of failure). Check the docs for the params: https://identityserver.github.io/Documentation/docsv2/endpoints/authorization.html

AuthorizeAttribute, anyway of checking in advance if this will pass

I have controller actions which have AuthorizeAttribute on them
Often someone will try an old url which will take them (forms authentication) to the logon page and then redirect to the url, but it may be for whatever reason that they are no longer allowed to access to that page
Is there any way of testing the url before redirecting?
I can decompose the url into the area/controller/action and test it but it feels clumsy to do that
(Extra info)
Our site is part of a product family, in the desktop app we can determine who has access to what parts. e.g. we may have a clocking page, a user accesses it and keeps the url. In the main product we remove their access to this page, the authorizeattribute now says they don't have access to it.
So we get
they try to access the url
forms authentication says they don't have access and reroutes to the logon page
they logon, however they still don't have access to this page and they are redirected again to the logon page.
With form authentication, please make sure you have set authentication cookie on logon page after validating user:
FormsAuthentication.SetAuthCookie(userId, rememberMe);
This will authenticate user in order to prevent from redirecting to Logon page again.
You can also check to see whether the user has been authenticated by:
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
var loggedOnUserId = HttpContext.Current.User.Identity.Name;
}

Pass argument from Identity Provider back to Relying Party after WSFed login

Is there a way to pass a value back to a relying party after login? e.g. on the querystring?
Background:
What we want to do is inform the relying party what action the user took, e.g. sign in or register, so that the relying party can display the appropriate confirmation message to the user. Because the relying party might link to a Sign Up page, but then instead of signing up the user signs in, so the relying party shouldn't display a "thanks for joining us" notification panel.
I tried adding &lastaction=signup to the returnUrl but that gets lost when the form is posted through Azure ACS.
Next attempt was to try to add lastaction to the wreply, like so:
WSFederationMessage message;
WSFederationMessage.TryCreateFromUri(uri, out message);
var signinMessage = wsFederationMessage as SignInRequestMessage;
if (signinMessage != null)
{
signinMessage.Reply += "?lastaction=hello";
...
In Fiddler I can see that the next POST to ACS posts to https://xxxxx.accesscontrol.windows.net/v2/wsfederation?lastaction=hello
But the lastaction is not passed on to my relying party.
We had a related problem: we wanted to let the RP know which authentication methods the user used when signing in. We solved this by creating a new "system" claim with our namespace, and put the information in there.
In our TokenService implementation, in the AddSecurityClaims method:
claimsIdentity.AddClaim(
new Claim(
String.Format("{0}/{1}", WellKnownConfiguration.TokenService.ClaimsNamespace,
ClaimsAuthenticationMethods), ((int) userAuthenticationMethods)));
Update
You mentioned you thought about using cookies. In that case, I would do the following. I would implement setting a cookie (e.g. when registration page) and then create one more "action" that would return the value of that cookie. When the app gets the POST request with the credentials, you'd perform a redirect (immediately) to that relaying action with a return url. That action would then append the value of the cookie and call the original RP, but a custom action, that would then properly display the view.
Think of it as a cookie proxy. To summarize, the process is as follows:
User hits the RP, action requires authentication
The RP redirects the user to the STS as per WS-Federation
STS issues a token, and also adds a cookie to its own domain
RP gets the authenticated user, redirects to STS Cookie Reader
STS redirects to RP's second screen that can handle the login properly
All in all, one more hop, but like I said, it's probably fast enough for the user to not notice and/or care.

How do I detect a federated identity from federatedpassivesignin control if the user is logged in at the STS

Hi I'm using the FederatedPassiveSignInControl on my asp.net site (called ChildSite) to get an user identity from a STS which is set up on another asp.net site (called ParentSite). The authentication of my site (ChildSite) is set to FormsAuthentication, so the FederatedPassiveSignInControl is located on ChildSite's forms authentication login page.
I have 2 scenarios. In the first the user logs in to ParentSite and continues to ChildSite via a link in ParentSite. In the second the user goes directly to ChildSite and logs in to ChildSite:
Scenario 1:
User opens ParentSite in browser
User logs in to ParentSite
ParentSite displays a link to ChildSite in browser
User clicks link to ChildSite
User goes to child site
Here the user comes to login page.
Wanted behavior is that the user is seamlessly redirected to the requested URL at ChildSite as he has already signed in at ParentSite.
Instead the login page is showed and the user has to click on the FedratedPassiveSigninControl button to retrieve his identity and then be redirected.
I cannot set the FedratedPassiveSigninControl property autosignin="true". It would always redirect the user to ParentSite when not logged in and that would break scenario 2.
I wonder how I detect, or how I get FederatedPassiveSignin Control (or other WIF components) to detect that the user is already logged in, not show FedratedPassiveSigninControl and just forward the user to his requested page.
Scenario 2:
User opens ChildSite in browser
User enters credentials in text inputs at ChildSite and clicks log in.
The requested page at ChildSite is displayed.
Am I missing something here?
Cheers,
mortb
The simplest approach would be to add an additional querystring parameter to your 4th step in Scenario 1 so that when you finally get to your login page, you have an "if" : "if the querystring parameter is present then AutoSignIn = true".
This is known as "home realm discovery" although your scenario is not typical as hrd usually involves two or more stses and here you have to differentiate between the sts and forms authentication.
This looks like a classic SSO scenario. ParentSite and ChildSite should probably be 2 different relying parties. If user goes to ParentSite, then whenever they hit a protected resource (anything that requires user to be authenticated), then they will be redirected to the STS for authentication. A session is established between the STS and the user browser and then and then the user returns to the ParentSite with a valid token (assuming a "happy path").
When they hit a protected resource on the ChildSite (e.g. through a link on ParentSite) they will be redirected again to the STS (e.g. they will be requesting a token specifically for ChildSite, a second Relying Party). This time, because there's already a session with the STS, the authentication step is completed already and a 2nd token is issued. All this works seamlessly for the user.
This chapter of the "Claims Guide" covers this scenario: http://msdn.microsoft.com/en-us/library/ff359102
An additional note: credentials should not be entered in any of the sites, but in the STS.

Resources