Access Control Service: Handling Errors

Posted by Your DisplayName here! on Least Privilege See other posts from Least Privilege or by Your DisplayName here!
Published on Sun, 29 May 2011 08:16:05 GMT Indexed on 2011/06/20 16:38 UTC
Read the original article Hit count: 238

Filed under:

Another common problem with external authentication is how to deal with sign in errors. In active federation like WS-Trust there are well defined SOAP faults to communicate problem to a client.

But with web applications, the error information is typically generated and displayed on the external sign in page. The relying party does not know about the error, nor can it help the user in any way.

The Access Control Service allows to post sign in errors to a specified page. You setup this page in the relying party registration. That means that whenever an error occurs in ACS, the error information gets packaged up as a JSON string and posted to the page specified. This way you get structued error information back into you application so you can display a friendlier error message or log the error.

I added error page support to my ACS2 sample, which can be downloaded here.

How to turn the JSON error into CLR types
The JSON schema is reasonably simple, the following class turns the JSON into an object:

[DataContract]
public class AcsErrorResponse
{
    [
DataMember(Name = "context"
, Order = 1)]
   
public string Context { get; set
; }

    [
DataMember(Name = "httpReturnCode"
, Order = 2)]
   
public string HttpReturnCode { get; set
; }

    [
DataMember(Name = "identityProvider"
, Order = 3)]   
   
public string IdentityProvider { get; set
; }

    [
DataMember(Name = "timeStamp"
, Order = 4)]
   
public string TimeStamp { get; set
; }

    [
DataMember(Name = "traceId"
, Order = 5)]
   
public string TraceId { get; set
; }

    [
DataMember(Name = "errors"
, Order = 6)]
   
public List<AcsError> Errors { get; set
; }

   
public static AcsErrorResponse Read(string
json)
    {
       
var serializer = new DataContractJsonSerializer(
typeof(AcsErrorResponse
));
       
var response = serializer.ReadObject(
new MemoryStream(Encoding.Default.GetBytes(json))) as AcsErrorResponse
;

       
if (response != null
)
        {
           
return
response;
        }
       
else
        {
           
throw new ArgumentException("json"
);
        }
    }
}

[
DataContract
]
public class AcsError
{
    [
DataMember(Name = "errorCode"
, Order = 1)]
   
public string Code { get; set
; }
       
    [
DataMember(Name = "errorMessage"
, Order = 2)]
   
public string Message { get; set; }
}

Retrieving the error information
You then need to provide a page that takes the POST and deserializes the information. My sample simply fills a view that shows all information. But that’s for diagnostic/sample purposes only. You shouldn’t show the real errors to your end users.

public class SignInErrorController : Controller
{
    [
HttpPost
]
   
public ActionResult
Index()
    {
       
var errorDetails = Request.Form["ErrorDetails"
];
       
var response = AcsErrorResponse
.Read(errorDetails);
       
return View("SignInError", response);
    }
}

Also keep in mind that the error page is an anonymous page and that you are taking external input. So all the usual input validation applies.

© Least Privilege or respective owner

Related posts about IdentityModel