I'm having some dramas making a call against a ServiceStack REST service which I've secured with an out of the box IdentityServer STS.
I'm making an AJAX call against the REST endpoint, and I'm not sure how one might setup a logon procedure to get a security token to pass. The REST endpoint is on a different domain than the website making the call. The info that I've found so far all seems to revolve around the procedure where the client makes a call to the secured resource gets a 302 redirect to the identityserver logon page, then after successful authentication gets a 302 redirect to either the realm or the reply depending on the configuration. I've hooked all this up correctly and it works great if I'm simply browsing through the REST services. However with regards to my web app, AJAX and 302s aren't exactly best friends, so ideally what I think I'd like to have is a REST endpoint from the same ServiceStack website that takes a username and password and returns a security token without the complication of any redirects (I'll handle the 401 redirects within my web application itself which I'll get when I turn off passiveRedirectEnabled in the web.config). Any thoughts on how one might achieve this with IdentityServer?
Cheers, Clint.
Completing the answer with the full REST endpoint:
In the ServiceStack web app:
Route to the logon endpoint in AppHost.cs with something like:
Then there's a simple username/password Request DTO
And the response DTO
Response DTO only needs to handle the POST - yes, you could add the URL/Password as parameters in the URL for a GET request, but this does not sound like it's recommended. In fact, you'd probably normally put this info in the Authorization header of the HTTP request but this makes your job in ServiceStack a little harder.
The ServiceStack web app Web.config should look fairly similar to this:
And finally, to authenticate a simple Javascript client app with the REST endpoint, POST the username and password to the logon endpoint of the servicestackwebapp, and then when you receive the response, post that back to the realm - doing so sets up the FedAuth cookies for your current session so you don't have to think about the token management client-side anymore.
Also, I should note that all of the HTTP endpoints above should instead be going over HTTPS - don't be silly like I've done in my example and send clear-text claims over HTTP.
Also after I'd implemented my solution I found this: http://msdn.microsoft.com/en-us/library/hh446531.aspx ... I wish I'd found it before, but it's reassuring to know I've implemented something similar to the Microsoft example - we diverge at the point where they convert to a Simple Web Token - I keep it as a SAML token and pass that (serialized) to the client instead.
My solution so far:
I've exposed an endpoint on the REST service that makes a call against the WS-Trust endpoint that IdentityServer provides by default. In .NET 4.5, you'll need to have a reference to Thinktecture.IdentityModel as UserNameWSTrustBinding is not available in System.IdentityModel see: What's the .NET 4.5 equivalent to UserNameWSTrustBinding?
The code to get the SAML2 security token from the endpoint looks like this:
This will authenticate based on a username and password and the endpointAddress parameter will look something like:
Then I'm serializing the security token as follows:
I believe the only remaining bit is establishing the FedAuth cookie(s), which I believe are set on first post of the security token to the secured web app.
Please weigh in with any improvements or suggestions. Thanks!