Mixing OAuth 2.0, Jersey and Guice to Build an Ecosystem of Apps
Hermann Burgmeier Matthias Miltz
JavaOne September 2013
Building an Ecosystem
● Co-Innovation with the community
Mobile platform support
SaaS model (Chaining of services)
● Provide (REST-)API for your service
● Ease of consumption for 3rd party developers
○ Many OAuth2 client libraries available
● Don’t worry about things that don’t deliver value:
○ Authentication
○ Authorization
Password Anti-Pattern
● Share your user/password directly
o Can you trust the site?
o Do you know if they store it?
o How to revoke access?
● Users get careless about sharing their
password
● No authorization of the requesting site
● No fine grained permissions
● Changing the password
frequently cuts off all sites
OAuth 2.0
● Protocol for authorization - not authentication
● Delegated model
o Fix the password anti-pattern!
o Trust relationship between resource, identity server
and client app
● Official IETF standard since Oct-2012 (http://oauth.net/2/)
● Goal was simplicity:
o Nounces / Signing of requests, anyone?
o No verification code
● Relies heavily on TLS/SSL
OAuth 2.0 - Implementations
● Early implementations by Google, Facebook, Github, etc.
● Java Open Source Server Implementations:
○ OAuth for Spring
○ Apis Authorization Server
○ Apache Oltu
○ Apache CXF
○ Restlet Framework
○ Jersey-OAuth2
■ Available on Github (github/hburgmeier/jerseyoauth2)
■ Based on dependency injection (Guice)
■ Variants for Jersey 1.x and 2.x
■ MIT License
OAuth 2 – Supported Flows
● Authorization Code
○ Strong authentication of the client
○ Trade authorization code for token
● Implicit
○ For clients that can’t keep a secret
● Resource Owner Password Credentials
○ If you and your users trust the client app...
● Client Credentials
○ To replace the common API key / API secret pattern
○ Used by Twitter
OAuth 2 for Mobile Native Apps
● Mobile applications can’t really keep a client secret
● Only two possible flows:
o Authorization Code
No client secret possible
o Implicit Grant
No refresh token
Based on “phony” Redirect-URL
● Standard proposes use of an internal/external browser
Our Demo
● Service to provide last coffee bean price
REST service returning JSON object
Implemented using JAX-RS 2.0 and Jersey 2.0
● What we want to do:
Enable OAuth 2.0 on the service
Javascript-based client as pure HTML application
• OAuth 2 Implicit Grant
Integrate external identity provider (Lenovo ID)
Hosted on OpenShift
Protocol Flow Implicit Grant
HTTP/1.1 302 Found Location: http://client.example.com/cb# access_token=mF_9.B5f-4.1JqM& expires_in=3600
GET /authorize? response_type=token& client_id=jsOnlyClientID& redirect_uri=https://client.example.com/cb
GET /resource/1 Authorization: Bearer mF_9.B5f-4.1JqM
Implementing Implicit Grant in
JavaScript
● Can’t keep a OAuth secret because JavaScript is
visible/debuggable in the browser
● Redirect URI is used for client authentication
● Access Token is transported as URL fragment
● Cross domain HTTP request to access
REST service
o Only works in modern browsers
o Requires a CORS enabled resource server
How to Enable Your Service
@Path("/coffee")
public class CoffeePriceService {
@GET
@Produces({ MediaType.APPLICATION_JSON })
public CoffeePrice get() {
…
}
How to Enable Your Service
@OAuth20
@AllowedScopes(scopes = {"espresso"})
@Path("/coffee")
public class CoffeePriceService {
@GET
@Produces({ MediaType.APPLICATION_JSON })
public CoffeePrice get() {
…
}
JAX-RS / Jersey 2.0 in our Example public class RestApplication extends Application {
@Inject
public RestApplication(ServiceLocator serviceLocator) {
DynamicConfiguration dc = Injections.getConfiguration(serviceLocator);
Injections.addBinding(Injections.newBinder(DefaultConfiguration.class).to(IRSConfiguration.class), dc);
Injections.addBinding(Injections.newBinder(AccessTokenVerifier.class).to(IAccessTokenVerifier.class), dc);
Injections.addBinding(Injections.newBinder(RequestFactory.class).to(IRequestFactory.class), dc);
dc.commit();
}
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> clazzes = new HashSet<Class<?>>();
clazzes.add(CoffeePriceService.class);
clazzes.add(JacksonFeature.class);
clazzes.add(OAuth2FilterFeature.class);
return clazzes;
}
}
JerseyOAuth2
DEMO
Authorization Server
● Web Application based on Guice / Dependency Injection
(Almost) everything is a service:
UserService, TokenService, ClientService, etc.
Use default or implement your own!
● Identity Provider:
Built-in (e.g. Container)
External (e.g. Lenovo ID)
● Contains user interface for approval/denial of
permissions (bring your own UI technology)
● Implements the authorization and token endpoint
Now It’s Your Turn...
Go enable your Jersey services:
● Maven:
○ <groupId> com.github.hburgmeier.jerseyoauth2 </groupId>
<artifactId> jersey-oauth2 </artifactId>
<version> 0.7 </version>
● GitHub:
○ https://github.com/hburgmeier/jerseyoauth2
● Sample Code:
○ https://github.com/hburgmeier/JavaOne2013
● Fork me!
Questions?
We are hiring in Freiburg, Germany!
We are hiring in Morrisville, NC!
Image Credits
Slide 2: By McKay Savage from London, UK [CC-BY-2.0], via Wikimedia Commons
Slide 4: By Hubert DENIES (Own work) [CC-BY-SA-3.0], via Wikimedia Commons
Slide 5: By Kweniston (Own work) [CC-BY-3.0], via Wikimedia Commons
Slide 6: By Ibonzer (Own work) [CC-BY-SA-3.0], via Wikimedia Commons
Slide 7: 2004 by Tomasz Sienicki [CC BY 2.5]
Slide 8: by Joe Shlabotnik [CC-BY 2.0] via Flickr
Slide 9: By Demilune [CC-BY-SA-2.5], via Wikimedia Commons
Slide 10: By David Bacon (Flickr: IMG_5126) [CC-BY-2.0], via Wikimedia Commons
Slide 11: By Andrés Nieto Porras from Palma de Mallorca, España ([C] Café Uploaded by russavia) [CC-BY-SA-2.0], via Wikimedia Commons
Slide 15: By Scott Schiller (Flickr: Master lock, "r00t" password) [CC-BY-2.0], via Wikimedia Commons
Slide 16: https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png