Dropwizard Deep Dive – Part 2: Authorization

Welcome back! This is Part 2 of a three-part series on extending Dropwizard to have custom authentication, authorization, and multitenancy. In Part 1, we set up custom authentication. When we left off, we had just used the Java annotations @RolesAllowed and @PermitAll to authenticate our resource methods, so they will only run for credentialed users. In this part, we’ll cover Dropwizard authorization. We are going to extend the code we added to check the role assigned to a user and further restrict our methods based on whether that matches.

We can turn role-checking on by enabling another dynamic feature within Jersey. In order for it work, we just need to set up a SecurityContext object that can tell if a given role applies and set that security context on each incoming request. Most of the code and techniques here are actually a core part of JAX-RS and can be used entirely outside of Dropwizard. All of the example code I’m going to show in my series lives in this repo if you want to follow along.

Enabling Role-Checking

To make Jersey check role annotations before each request, we need to enable the RolesAllowedDynamicFeature, which is a core part of Jersey, not Dropwizard. We can enable it in our app like so:

environment.jersey().register(RolesAllowedDynamicFeature.class);

If you just activate that, you’ll notice that you can no longer use any of the endpoints annotated with @RolesAllowed (though those with @PermitAll still work). These endpoints will return a 403, because they have no way to validate their set of roles against the logged-in user. Fixing that is our next step.

Custom Security Context

A SecurityContext is a core JAX-RS object that is attached to a request context for the purposes of validating security. We are going to modify our auth filter to attach a security context to each authenticated request. The security context we attach will have logic to check the roles in the @RolesAllowed annotation against the authenticated user (to which we will also add a role field).

First off, we need to create a custom subclass of SecurityContext that can check our roles:

public class CustomSecurityContext implements SecurityContext {
  private final CustomAuthUser principal;
  private final SecurityContext securityContext;
  public CustomSecurityContext(CustomAuthUser principal, SecurityContext securityContext) {
    this.principal = principal;
    this.securityContext = securityContext;
  }
  @Override
  public Principal getUserPrincipal() {
    return principal;
  }
  @Override
  public boolean isUserInRole(String role) {
    return role.equals(principal.getRole().name());
  }
  @Override
  public boolean isSecure() {
    return securityContext.isSecure();
  }
  @Override
  public String getAuthenticationScheme() {
    return "CUSTOM_TOKEN";
  }
}

The most important part of this is the isUserInRole method which drives our Dropwizard authorization code. It will be called once for each role we define in our @RolesAllowed annotation, and if it returns “true” for any of them, we are authorized to use the method.

Now we need to update our auth filter method to attach a security context whenever we authenticate a user. We don’t have to do anything when there is no authenticated user, because the default security context has no user attached and will fail authorization checks. We also need to make sure to set the @Prioroity of our auth filter to Priorities.AUTHENTICATION so this code will run before any other filters that depend on authentication.

@PreMatching
@Priority(Priorities.AUTHENTICATION)
public class CustomAuthFilter extends AuthFilter<CustomCredentials, CustomAuthUser> {
  private CustomAuthenticator authenticator;
  public CustomAuthFilter(CustomAuthenticator authenticator) {
    this.authenticator = authenticator;
  }
  @Override
  public void filter(ContainerRequestContext requestContext) throws IOException {
    Optional<CustomAuthUser> authenticatedUser;
    try {
      CustomCredentials credentials = getCredentials(requestContext);
      authenticatedUser = authenticator.authenticate(credentials);
    } catch (AuthenticationException e) {
      throw new WebApplicationException("Unable to validate credentials", Response.Status.UNAUTHORIZED);
    }
    if (authenticatedUser.isPresent()) {
      SecurityContext securityContext = new CustomSecurityContext(authenticatedUser.get(), requestContext.getSecurityContext());
      requestContext.setSecurityContext(securityContext);
    } else {
      throw new WebApplicationException("Credentials not valid", Response.Status.UNAUTHORIZED);
    }
  }
  ...
}

Dropwizard Authorization Complete

With the AuthDynamicFeature enabled and our security context attached to authenticated requests, we now have role-based authentication on every incoming request. If you’ve been following Parts 1 and 2 of this post, you’ll see that we have both Dropwizard authentication and Dropwizard authorization for our API. This is probably enough for many apps, but in Part 3, I’ll show you how you can also add multitenancy to a Dropwizard application using a similar annotation-based approach.

You can see the code for just what we’ve done for Parts 1 and 2 here and the complete code for all three parts here.

The post Dropwizard Deep Dive – Part 2: Authorization appeared first on Atomic Spin.

Dropwizard Deep Dive – Part 1: Custom Authentication

This is Part 1 of a three-part series on extending Dropwizard with custom authentication, authorization, and multitenancy. For Part 1, we are going to go over adding custom authentication to Dropwizard.

If you don’t already know, Dropwizard is an awesome Java web API framework. It is my preferred web stack. I’ve written about it previously in: Serving Static Assets with DropWizard, Using Hibernate DAOs in DropWizard Tasks, and Hooking up Custom Jersey Servlets in Dropwizard (note that some of those posts are out-of-date for newer versions of Dropwizard).

It already comes with out-of-the-box support for http basic authentication and OAuth in the dropwizard-auth package. However, in a recent project, I needed to integrate a Dropwizard API with an existing API from another platform using a custom authentication scheme. Fortunately for me, Dropwizard exposes a set of extendible privative for authentication that I was able to leverage in my solution. All of the example code I’m going to share in my posts lives in this repo, if you want to follow along.

Disclaimers

Before we begin, I want to share a couple of disclaimers:
1. This was written for Dropwizard 0.9.x (the current version as of this writing). Future changes to Dropwizard may alter or invalidate details of this post. Be aware if you are using a later version.
2. This post uses hibernate for the database integration. While much of what we do here is possible with JDBI or other database integrations, I am not going to cover or discuss those. I will likely not be able to answer questions about them.

Now let’s get to work.

Adding Auth Annotations

Dropwizard allows us to use the role annotations under the javax.annotation.security package, @RolesAllowed, @PermitAll, and @DenyAll to enforce authentication on our resource methods. You can add them to each method to set the permissions like so:


@POST
@UnitOfWork
@RolesAllowed({"MANAGER"})
public Widget createWidget(Widget widget) {
  WidgetModel widgetModel = widgetDAO.createWidget(widget);
  return new Widget(widgetModel.getId(), widgetModel.getName(), widgetModel.getScope());
}
@GET
@Path("/public")
@UnitOfWork
@PermitAll
public List getPublicWidgets() {
  return getWidgetsForScope(WidgetScope.PUBLIC);
}
@GET
@Path("/private")
@UnitOfWork
@RolesAllowed({"EMPLOYEE", "MANAGER"})
public List getPrivateWidgets() {
  return getWidgetsForScope(WidgetScope.PRIVATE);
}
@GET
@Path("/top-secret")
@UnitOfWork
@RolesAllowed({"MANAGER"})
public List getTopSecretWidgets() {
  return getWidgetsForScope(WidgetScope.TOP_SECRET);
}

In the above example, you can see that only users with the MANAGER role are allowed to create new widgets or view top-secret widgets. Users with an EMPLOYEE or MANAGER roles can see internal widgets, and anyone can see public widgets. It is important to note that if we don’t put any of these annotations on to a resource method, it will be open to anyone by default. This is different from the @PermitAll annotation, which still authenticates a user and just disregards what roles they have. To protect against this, I usually use reflection to write a test like the one here that ensures every resource method has one of these annotations.

If you just add these roles and start up your application, you are going to be disappointed. These annotations don’t have any handler by default, so we are going to need to add an AuthFilter to Dropwizard to make them do something.

Adding an AuthFilter

In order to make our annotations do something, we need to use the tools in the dropwizard-auth package (which you’ll need to add to your dependency list). If we were just using HTTP basic auth or OAuth, we could use the out-of-the-box tools for those and hook them up to a role schema. However, since we are hooking into a custom authentication scheme, we are going to have to create our own stuff using the package primitives.

The first thing we need to create is a Jersey filter that will run before each request and execute our authentication code. Dropwizard provides a convenient base class called AuthFilter that will do the job. A bare-bones AuthFilter is parameterized to a type of credentials and security principal and would look like this:


@PreMatching
@Priority(Priorities.AUTHENTICATION)
public class CustomAuthFilter extends AuthFilter {
  @Override
  public void filter(ContainerRequestContext requestContext) throws IOException {
    throw new WebApplicationException(Response.Status.UNAUTHORIZED);
  }
}

We can register the filter inside our Dropwizard application’s run method using the AuthDynamicFeature like so:


CustomAuthFilter filter = new CustomAuthFilter();
environment.jersey().register(new AuthDynamicFeature(filter));

Now our filter will run before each request annotated with @RolesAllowed, @PermitAll, or @DenyAll to authenticate the user. Right now, though, our filter just rejects every request with a 401 status code. The next thing we need to do is add an Authenticator which will actually run the logic of authenticating a user’s credentials.

Adding an Authenticator

Our authenticator exposes a single method, authenticate, which takes in a CustomCredentials as an argument. The authenticator then uses the userId and token in the credentials to authenticate the user against the token stored in our database for that user. If the token matches, we return the user wrapped as an optional—otherwise, we return an empty optional. Also note that since we are using hibernate, we need to new up our authenticator using UnitOfWorkProxyFactory like so:


CustomAuthenticator authenticator = new UnitOfWorkAwareProxyFactory(hibernate)
      .create(CustomAuthenticator.class, new Class[]{TokenDAO.class, UserDAO.class}, new Object[]{tokenDAO, userDAO});

And our whole authenticator looks like this:


public class CustomAuthenticator implements Authenticator {
  private TokenDAO tokenDAO;
  private UserDAO userDAO;
  public CustomAuthenticator(TokenDAO tokenDAO, UserDAO userDAO) {
    this.tokenDAO = tokenDAO;
    this.userDAO = userDAO;
  }
  @Override
  @UnitOfWork
  public Optional authenticate(CustomCredentials credentials) throws AuthenticationException {
    CustomAuthUser authenticatedUser = null;
    Optional user = userDAO.getUser(credentials.getUserId());
    if (user.isPresent()) {
      Optional token = tokenDAO.findTokenForUser(user.get());
    
      if (token.isPresent()) {
        TokenModel tokenModel = token.get();
    
        if (tokenModel.getId().equals(credentials.getToken())) {
          authenticatedUser = new CustomAuthUser(tokenModel.getUser().getId(), tokenModel.getUser().getName());
        }
      }
    }
    
    return Optional.fromNullable(authenticatedUser);
  }
}

Now we just need to hook up our CustomAuthFilter to our CustomAuthenticator by calling the authenticate method with some credentials. We’ll create the credentials in our auth filter by parsing our request context. (In our case, this means pulling the credentials out of cookies.)


public class CustomAuthFilter extends AuthFilter {
  private CustomAuthenticator authenticator;
  public CustomAuthFilter(CustomAuthenticator authenticator) {
    this.authenticator = authenticator;
  }
  @Override
  public void filter(ContainerRequestContext requestContext) throws IOException {
    Optional authenticatedUser;
    try {
      CustomCredentials credentials = getCredentials(requestContext);
      authenticatedUser = authenticator.authenticate(credentials);
    } catch (AuthenticationException e) {
      throw new WebApplicationException("Unable to validate credentials", Response.Status.UNAUTHORIZED);
    }
    
    if (!authenticatedUser.isPresent()) {
      throw new WebApplicationException("Credentials not valid", Response.Status.UNAUTHORIZED);
    }
  }
  private CustomCredentials getCredentials(ContainerRequestContext requestContext) {
    CustomCredentials credentials = new CustomCredentials();
    try {
      String rawToken = requestContext
        .getCookies()
        .get("auth_token")
        .getValue();
    
      String rawUserId = requestContext
        .getCookies()
        .get("auth_user")
        .getValue();
    
      credentials.setToken(UUID.fromString(rawToken));
      credentials.setUserId(Long.valueOf(rawUserId));
    } catch (Exception e) {
      throw new WebApplicationException("Unable to parse credentials", Response.Status.UNAUTHORIZED);
    }
    return credentials;
  }
}

Notice that we parse the credentials out of the request cookies and create a CustomCredentials instance. We then pass those credentials to the CustomAuthenticator in the filter method. If the authenticator returns a user, we are properly authenticated. Otherwise, we abort the request with a 401 error.

Custom Authentication Complete

And with that, we now have custom authentication on all of our annotated resource methods. None of them can be successfully called without a valid userId and token combination in the request cookies.

But what about those roles that we listed in the method with the @RolesAllowed annotation? Right now, any of the methods are open to any authenticated user. To check the roles on the user requires a little more work on our part, which we will cover in Part 2.

You can see the code for Part 1 here and the complete code for all three parts here.

The post Dropwizard Deep Dive – Part 1: Custom Authentication appeared first on Atomic Spin.

Authentication and Authorization: OpenID vs OAuth2 vs SAML

My current project at AO has provided a lot of opportunity to learn about web security and what’s going on when you click that ubiquitous “Sign in with Google/Facebook” button. As both a computer developer and an end user, I want applications that are secure without being too difficult to use.

Looking for an option to fit both our application and our customer’s security policies, we investigated OpenID, OAuth2, and SAML.

Authorization & Authentication Basics

Our project, a single-page application, will be a public-facing website. We want to restrict access to registered users only. Furthermore, we want to tailor each user’s experience, and the amount and type of data that they can view, to their individual roles and access levels.

In other words, we want to be able to authenticate and authorize each user. Authentication means verifying that someone is indeed who they claim to be. Authorization means deciding which resources a certain user should be able to access, and what they should be allowed to do with those resources. Oftentimes, as in our case, an application will require a little bit of both.

With sites like Facebook or Google, a user can log in to one application with a set of credentials. This same set of credentials can then be used to log in to related websites or applications (like websites that ask you, “Sign up with Facebook or Google account?”).

Likewise, a business may have an internal-facing employee portal with links to intranet sites regarding timesheets, health insurance, or company news. Rather than requiring an employee to log in at each website, a better solution would be to have the employee log in at a portal, and have that portal automatically authenticate the user with the other intranet sites. This idea, called single sign-on (SSO), allows a user to enter one username and password in order to access multiple applications.

The benefits are pretty nice for the user. The use of linked identities means they have to manage only one username and password for the related websites. The user experience is better for them, as they can avoid multiple logins. A user’s (single set of) credentials will be stored in one database, rather than multiple credentials stored across multiple databases (with, let’s be honest, likely repeated passwords). This also means that developers of the various applications don’t have to store passwords. Instead, they can accept proof of identity or authorization from a trusted source.

There are multiple solutions for implementing SSO. The three most common web security protocols (at the time of this writing) are OpenID, OAuth, and SAML. Implementations and libraries exist in multiple languages already, and going with a standardized protocol allows better interoperability than a custom solution.

OpenID

OpenID is an open standard for authentication, promoted by the non-profit OpenID Foundation. As of March 2016, there are over a billion OpenID-enabled accounts on the internet, and organizations such as Google, WordPress, Yahoo, and PayPal use OpenId to authenticate users.

A user must obtain an OpenID account through an OpenID identity provider (for example, Google). The user will then use that account to sign into any website (the relying party) that accepts OpenID authentication (think YouTube or another site that accepts a Google account as a login). The OpenID standard provides a framework for the communication that must take place between the identity provider and the relying party.

This exchange can be compared to a border crossing.  Imagine that Alice is a Canadian citizen who wants to visit the US. At the border, the US asks for proof of identity (her passport). Because the US government trusts the Canadian government to accurately provide identification for its citizens, the US accepts Alice’s passport as reliable proof of her identity, and thus, lets her enter the US. In this example, Alice is the end user, the US is the relying party, and Canada is the identity provider.

This exchange works because Alice can provide proof of identity to the US that originates from an entity that the US trusts. Similarly, the relying party (or website that a user is trying to log in to) must trust the OpenID identity provider that will verify the user’s identity.

On a website, the exchange looks like this:

Screen Shot 2016-05-16 at 8.30.55 AM

Let’s return to Alice, who wants to log in to her MyBlogger account (the relying party). She navigates to the login screen, where she is offered a “Sign in with Google” option. She clicks that, and MyBlogger initiates association with Google and requests and receives an association handle. MyBlogger then forwards Alice to the Google login page. She enters her credentials, and Google validates them. She is then redirected back to MyBlogger, along with a token stating that Google believes she is who she claims to be (Alice). MyBlogger trusts this token and creates a session for her.

Notes:

  1. OpenID is technically a URL that a user owns (e.g. alice2016.openid.com), so some websites offer the option to manually enter an OpenID.
  2. The latest version of OpenID is OpenID Connect, which combines OpenID authentication and OAuth2 authorization
  3. Screen Shot 2016-05-16 at 8.29.34 AMFacebook previously used OpenID but has since moved to Facebook Connect.

OAuth2

By contrast, OAuth2 is an open standard for authorization. Confusingly, OAuth2 is also the basis for OpenID Connect, which provides OpenID (authentication) on top of OAuth2 (authorization) for a more complete security solution. OpenID Connect (OIDC) was created in early 2014. This primer will instead focus on OAuth2 by itself, not as a part of OIDC.

OAuth2 provides secure delegated access, meaning that an application, called a client, can take actions or access resources on a resource server on the behalf of a user, without the user sharing their credentials with the application. OAuth2 does this by allowing tokens to be issued by an identity provider to these third-party applications, with the approval of the user. The client then uses the token to access the resource server on behalf of the user.

Yet Twitter’s OAuth guide says that OAuth2 is an authentication standard. So what gives? As it turns out, authorization can be used as a form of pseudo-authentication.

An authorization use case of OAuth2 might be as follows: Alice is leaving town and she wants her friend Bob to house-sit. Alice gives Bob the house key, and he now has access to enter the house. The key gives him authorization to enter the house, as authorization relates to which resources a user should have access to, and what they can do with those resources. In this metaphor, the homeowner is the user, Bob is the client, the door lock is the identity provider, and the house is the resource server.

This can be twisted into a pseudo-authentication use case by assuming that the person who has the house key is the homeowner. However, as we can see with Bob house-sitting for Alice, this is not always the case.

Online, an OAuth2 use case might look like this:  Alice signs up for a new account at NewApp and is offered the option to see which of her friends already use NewApp so she can connect with them. There’s a button labeled “import contacts from Facebook.” Alice clicks that button, and she is redirected to Facebook to log in. Alice successfully logs in and is asked if she wants to share her Facebook friend list with NewApp. She clicks yes, and is forwarded back to NewApp along with a token. NewApp now has permission (with the token) to access Alice’s friend list, without her sharing her credentials directly with NewApp. This eliminates the risk of NewApp logging into Facebook on Alice’s behalf and doing things she wouldn’t want (posting status updates, changing her password, etc.).

SAML

SAML is the oldest standard of the three, originally developed in 2001, with its most recent major update in 2005. SAML, pronounced “sam-el,” stands for Security Assertion Markup Language. It’s an open standard that provides both authentication and authorization.

Similar to the terminology of the other two standards, SAML defines a principal, which is the end user trying to access a resource. There is a service provider, which is the web server that the principal is trying to access. And there is an identity provider, which is the server that holds the principal’s identities and credentials.

The US/Canada metaphor can be used here, as well. Alice wishes to enter the US from Canada. The US, wishing to verify her identity or other information about her–perhaps whether she has a valid driver’s license that will allow her to drive in the US)–makes a request to Canada for authentication and/or authorization information regarding Alice. Canada responds by sending the requested information to the requested address, along with some proof that Canada was indeed the sender of the message. All metaphors break down eventually, but this proof might take the form of a passport, as before, or official government documents or visas (where authorization requests are involved). And, as before, the system is predicated on US trust that Canada is issuing driver’s licenses, visas, etc. properly.

In our example, Alice is the principal, the US is the service provider, and Canada is once again the identity provider. The request made to Canada by the US is analogous to an XML message that states what information is being requested, who is asking, and to whom the response should be returned. Canada’s response would be called an assertion, in SAML terms (similar to a token for OpenID or OAuth2). This assertion can contain statements about authentication, authorization, and/or attributes (specific information about a user, such as email or phone number).

The SAML 2.0 specification defines assertions (as discussed above); protocols, which are assertion requests and responses; bindings, or how these requests and responses happen between the service provider and identity provider, using standard communication methods (e.g. HTTP POST); and profiles, which are combinations of assertions, protocols and bindings for various use cases, like SSO.

An SSO use case might look like this: Alice is a manager at Acme Corp. She accesses Acme Corp’s intranet portal, where she logs in with her credentials. After logging in, she can click on a number of links that may be of interest to her (payroll, company news, Salesforce, etc.). She clicks on the Salesforce link, which contains a SAML assertion about Alice. She is forwarded to Salesforce, which receives the SAML assertion. Salesforce trusts Acme Corp, and thus trusts the assertion. Using information in the token, Alice is automatically logged in, and the appropriate data is shown to her based on attributes in the assertion.

Summary

These three options are summarized in the table.  Our application implements IdentityServer, a .NET framework that implements both OAuth2 and OpenID Connect.

OAuth2
OpenId
SAML
Token (or assertion) format
JSON or SAML2
JSON
XML
Authorization?
Yes
No
Yes
Authentication?
Pseudo-authentication
Yes
Yes
Year created
2005
2006
2001
Current version
OAuth2
OpenID Connect
SAML 2.0
Transport
HTTP
HTTP GET and HTTP POST
HTTP Redirect (GET) binding, SAML SOAP binding, HTTP POST binding, and others
Security Risks
Phishing
OAuth 2.0 does not support signature, encryption, channel binding, or client verification.  Instead, it relies completely on TLS for confidentiality.
Phishing
Identity providers have a log of OpenID logins, making a compromised account a bigger privacy breach
XML Signature Wrapping to impersonate any user
Best suited for
API authorization
Single sign-on for consumer apps
Single sign-on for enterprise
Note:  not well suited for mobile

The post Authentication and Authorization: OpenID vs OAuth2 vs SAML appeared first on Atomic Spin.

My Oracle Support: Authenticate with CLI

I was wondering since some times how I could authenticate on MOS using CLI. Now I got my answer: By reversing the whole SSO auth process in a python script that generate a cookies.txt file, usable with wget.

I know that a simpler method exists using directly wget, but as it doesn't work with every MOS page, I'll prefer a more generic way of doing things.

Here is a quick how to use:

  1. Edit MOSLogin.py and setup variables inside.
  1. Install python dependencies (linux/debian):
apt-get install python-pip
pip install BeautifulSoup
pip install requests
  1. Run the script
$ ./login.py 
[-] Initialization...done
[-] Gathering JSESSIONID..done
[-] Trying loginSuccess.jsp...done
[-] Signing in...done
[-] Trying to submit credentials...done
[-] Checking that credentials are valid...done
[-] Logged-in.
  1. Use the cookies.txt with wget
wget --load-cookies=/tmp/cookies.txt --save-cookies=/tmp/cookies.txt --no-check-certificate http://MOSURL

With a little bit of time and fun, you can imagine every tool based on this to ease your sysadmin life. You can even fetch your SR summary/updates using this cookie...

Get the MOSLogin.py file...