CLARIN/OAuth2
For CLARIN's security for web services OAuth 2.0 was identified as one of the possible solutions. We are currently creating a test service.
Documents
- draft-ietf-oauth-v2 draft-ietf-oauth-v2-bearer draft-ietf-oauth-assertions draft-ietf-oauth-saml2-bearer
- Introducing OAuth 2.0
- OAuth flows
- The Current State of OAuth 2
- What is 2 legged OAuth? (and what not)
- tokens: Simple Web Token (SWT) JSON Web Token (JWT)
- Real-world usage
Software
AS=Authorization Server, RS=Resource Server
- PHP: oauth2-php (client draft 10, server draft 20; more at github and forks; setup and testing)
- PHP: OAuth2lib RS+AS+client only for SAML authorization code
- Ruby: rack-oauth2 RS+AS+client with bearer token support
- Ruby: rack-oauth2-provider AS for SAML extension token prototype
- Java: resthub-oauth2 client
- Java: Apache Amber RS+AS+client
- Python: python-auth2 client
- Perl: Net::OAuth2 client
- R: oauth
Options for the use-case
A user accesses a web portal ("client" in OAuth2 terminology) for editing data. He logs in using SAML SSO. Somewhere in the process, the portal needs to access the user's data on service B. Using the existing SAML SSO login, the portal accesses service B without having to ask the user's confirmation again.
The access to service B can be implemented using OAuth 2.0. In this case it is a three-legged OAuth 2 flow, with three different endpoints: authorization endpoint doing user authentication, token endpoint handing out the access token (AS), and the resource endpoint providing the service to the client or user (RS).
There are several ways to do this. Let's see what existing implementations provide.
- OAuth2lib: client does SAML SSO login. By presenting the returned attributes to the AS, it obtains an access token for the RS.
- demo; select default-sp for Feide's OpenIdp or default-sp-userpass and login with demo/demo
- uses Simple Web Tokens (SWT)
- :) AS trusts RS; signed access token by shared secret
- :(( AS fully trusts client to supply user attributes; possible solutions:
- Either client could pass signed SAML statement from IdP to AS, which then can verify that.
- related to draft-ietf-oauth-saml2-bearer (and expired draft-campbell-oauth-saml); AS would need to check that it was signed to the portal's SAML SP endpoint according to draft :/
- :( would require signatures of all IdPs at each AS (in addition to clients); can be done using eduGAIN
- :( requires patching of OAuth2lib client (and maybe SimpleSAMLphp too; mod_shib would work) to send signed SAML
- :( requires patching of OAuth2lib AS to verify SAML (possibly with help of SimpleSAMLphp)
- the IdP can be seen as a non-standard authorization endpoint
- Or introduce an authorization endpoint that does SAML SSO login for the client
- could return user attributes token to client (besides to the AS)
- :) signed token so AS can check it was supplied by the authorization endpoint (shared secret)
- :) client does not need to know about SAML SSO
- :) allows to use generic OAuth2 clients (can switch authentication methods by adapting authorization endpoint only)
- :( requires development of new service endpoint
- :( requires patching of OAuth2lib AS to accept SWT from client
- Either client could pass signed SAML statement from IdP to AS, which then can verify that.
- Apache Amber full suite
- :( found no SAML-support (yet?)
- :( trouble building the thing when I tried
- rack-oauth2-provider converts a SAML assertion to a signed SWT token
- might be an option for the authorization endpoint mentioned above?
- oauth2-php server+client
- not ready-to-go, but looks like it could be an alternative library to build upon
- was able to create a client interfacing with Github
- python-oauth2 server+client library
- not ready-to-go, also something to build upon
- rack-oauth2 server+client
- nice library, not ready-to-go, something to build upon
Conclusion: it looks like most implementations are libraries, not complete solutions. I have found only OAuth2lib to provide a 'generic' AS that is ready-to-go. The downside is that it completely trusts the client to supply who's logged in, without any way to check that the IdP asserted this. Two options were mentioned to fix this. Both require some coding work.
There are a number of ways to get an OAuth2 access token. One of them is using an assertion. Another is using client credentials, or by means of a refresh token. OAuth2lib seems to support only client credentials with a form of assertion (who's logged in). When in the future other ways to obtain an access token would be required, it's advisible to look more into the other libraries that already implement these.
If the client can be trusted fully, OAuth2lib can be used directly.