Wednesday, May 14, 2008

How to use SAML with REST Web Services

The Problem
OASIS Web Services Security describes how to use SAML with SOAP web services. The signed SAML Assertion should be added to the SOAP header... and so on. However, there is no specification that describes how to add SAML to REST web services. The reason that there is no such specification is simple: REST is not a standard, but it's an architectural style. So it's impossible to define standard that is not based on standard.

And still we would like to support SAML for our REST web services. Why? The same reason we support SAML for SOAP web services: it's a standard, it's convenient, many frameworks start to support it and so on.

The Solution
The solution is quite simple. Since REST web services are based on HTTP protocol we can use the HTTP Redirect Binding (see SAML Bindings, 3.4) to send the Unsolicited Responses (see SAML Profiles, 4.1.5). Since there is no problem to add the necessary query parameters to any HTTP method, the HTTP Redirect Binding with Unsolicited Responses covers the same scenario we have with SOAP without defining the additional standards.

Concerns
The only concern I have about this solution is the url length. Theoretically the url length is infinite, but of cause it cannot be supported. Each vendor limits the url length in its way and if the SAML Response will be very long, it may cause the url to be truncated. Which will cause failure to parse or validate the SAML Response.

Conclusion
Unless we send very long messages, we can send SAML with REST web services using the HTTP Redirect Binding. Although it is not a standard, it still a standard way to do things and it should work.

Who do you think?


Recommended Reading

1. Restful Web Services
2. REST in Practice: Hypermedia and Systems Architecture
3. Securing Web Services with WS-Security: Demystifying WS-Security, WS-Policy, SAML, XML Signature, and XML Encryption

12 comments:

Unknown said...

Why not put the SAML response in the http header? Most people developing REST clients are already familiar with headers. We would have to agree on a key, but that has to be done anyways with URLs.

Tarlog said...

Hi Matt,

Thanks for your comment.

Of course it's possible to put SAML in a custom header. The only problem you mentioned yourself: there is a need to agree on a header name. While if you use URL binding, all parameter names are already defined for you. So it's "almost standard".

I think that in cases where URL cannot become too long, it's better to use URL binding.
While in other cases there is a need to use a custom header.

kanchanna said...

why not put the SAML response in the Authorization parameter of the http header?

Tarlog said...

@karla
Actually it's the same as putting it in custom header, since it's not a standard.

grzesiek said...

So I can use SAML with REST Web Services to authenticate myself in REST WS but how can I achieve confidentiality for communication between user(client) and REST WS. With SOAP I could use WS-Security (XML Encrytion and XML Singature) and WS-SecureConversation (to bind session key from SAML with SecureContex) and later encrypt communication between user and WS according to this contex. Is there a way to do the same (similar) thing with REST WS or am I forced to do it "lower" and use SSL(https)? Basiclly is there a different way to encrypt communication between user and REST WS then SSL?

grzesiek said...
This comment has been removed by the author.
Tarlog said...

@grzesiek
Except of using TLS (SSL), there is nothing standard I know about.
Of course you can encrypt the data yourself.
But I guess it makes sense only if you encrypt only small parts of the data, otherwise SSL should be a better choice.

grzesiek said...

thx for your answer. could you explain why encryption on my own make sense only for small parts of data?
In my case user client is a http+js+jQuery and rest ws is in c#. any idea how could i organize encryption on my own? I know that if both sides of communication would be in java (or c#) i could use handlers (or c# hadnler equivalent) to encrypt whole traffic from client to ws and to decrypt this traffic on ws side. in opposite direction analogously. but how i can make it in js?

Tarlog said...

Using a proprietary encryption mechanism can be effective only if you pass large chunks of data, while only parts of them are encrypted (for example think about an order that contains a lot of items, but only a credit card need to be encrypted). I can hardly believe that a proprietary encryption will be as effective as SSL, if you encrypt the whole data.

Also, an encryption from the JS won't be a very good idea. There are some libraries [1] that implement encryption in JS, but they are quite slow. Also I'm quite not sure how are you going to keep the keys secured, unless you use SSL. And, well, we are back to the SSL solution, so you don't need a proprietary solution.

[1] http://code.google.com/p/crypto-js/

Tarlog said...

Btw, did you ever think why SOAP needs the WS-Encryption, while REST usually relies on SSL?

The reason is that SOAP is transport independent. It isn't used only with HTTP, but also with JMS or even MAIL protocols (e.g. smtp). So when using SOAP, you cannot rely on the transport for security.

But when using REST with HTTP, you can fully rely on HTTPS.

grzesiek said...

Thx a lot!!

Stefan Rasmusson said...

Why would you want to send the a response in the WS call and not just the SAML Assertion as in the case with SOAP WS-Security?