javaone 2013 bof 3861 - mixing oauth 2.0, jersey and guice to build an ecosystem of apps
TRANSCRIPT
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