07. Authentication. Filters. Basic Authentication.

Java Brains tutorial shows several ways of authentication.

1. Filters

First introduces the concept of filters that have methods to implement from the interfaces:

  • ContainerRequestFilter
  • ContainerResponseFilter
In the response, the given example, a parameter is added to the header ("MyHeaderParam" with value "Ximo Dante"). Notice the @Provider annotation



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package org.ximodante.jaxrs.client;

import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;

@Provider
public class RestFilter implements ContainerRequestFilter, ContainerResponseFilter{

 //01. Method from ContainerRequestFilter interface. Notice it has only one parameter
 @Override
 public void filter(ContainerRequestContext requestContext) throws IOException {
  //Shows headers in the 
  System.out.println("Request filter");
  System.out.println("Headers: " + requestContext.getHeaders());
  
  
 }
 //02. Method from ContainerResponseFilter interface. Notice it has 2 parameters
 @Override
 public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
   throws IOException {
  // Add a header to the response
  responseContext.getHeaders().add("MyHeaderParam", "Ximo Dante");
  System.out.println("Response filter");
  System.out.println("Headers: " + responseContext.getHeaders());
 }
}

In the tutorial videos, it is shown how to use Postman to see the headers

2. Authentication Mechanisms


2.1 Session authentication:

In the session authentication, the user and password is provided and the server returns a session id that should be supplied at every request to the server. This session id is saved in the client by means of a cookie. But REST is STATELESS, so no sessiñon is stored. This is not valid for REST services

2.2 Classic User-password authentication

As REST is stateless, the credentials should be passed in every request. They are normally in the header. You must use HTTPS or else this credential may be sniffed.

To send authentication is:

Authorization: Basic xxxxxxxxxxxxxxxxx

where xxxxxxxxxxxxxxxxx is username:password (user name and password separated by a colon) in base64 encoding

2.3 Digest access authentication

A secret key is encripted and is used.

2.4 Asymmetric cryptography

The classic use of a private key and a public key to encrypt and decrypt information

2.5 OAuth version 1 and 2

Are 2 different protocols

2.6 JSON Web Tokens

...

3. Basic Authentication


Here is a "Basic Authentication" that Postman lets you use:



You can see how user and password are supplied. But also  the conversion



3.1 Secure API

First, let's create a secure resource class


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package org.ximodante.jaxrs;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("secured")
public class MySecureResource {
 @GET
 @Produces (MediaType.TEXT_PLAIN)
 public String securedMethod() {
  return "You need basic login to use this API! But you have been loogged in!,Cheers!";
 }
}

Nothing is special unless we add a filter. There are some things to consider:

  • Line 18: The secure API is restricted only to the prefix "secured"
  • Lines 14 & 15: For "Base authorization" only the header marked with "Authorization" with "Basic" has user and password in Base64 code which is decoded in line 36
  • Line 51: A response to an unauthorized request is supplied.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package org.ximodante.jaxrs;

import java.io.IOException;
import java.util.List;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.glassfish.jersey.internal.util.Base64;

@Provider
public class SecureFilter implements ContainerRequestFilter {

 private static String AUTH_HEADER_KEY = "Authorization"; 
 private static String AUTH_HEADER_PREFIX = "Basic"; 
 
 //00. If no secure prefix is supplied then all the request will be secured
 private static String SECURED_URL_PREFIX = "secured";
 
 @Override
 public void filter(ContainerRequestContext requestContext) throws IOException {
  
  boolean noAuth=true;
  // 00. Select the path to secure
  if(requestContext.getUriInfo().getPath().contains(SECURED_URL_PREFIX)) {
  
   //01. Get the header key
   List<String> authHeader =requestContext.getHeaders().get(AUTH_HEADER_KEY);
   if (authHeader !=null && authHeader.size() >0) {
   
    //02. Remove the "Basic" prefix
    String authToken=authHeader.get(0)
     .replaceFirst(AUTH_HEADER_PREFIX, ""); System.out.println(authToken);
    
    //03. Decode from Base64 
    String decodedString=Base64.decodeAsString(authToken.trim());
    System.out.println(decodedString);
    
    String[] s=decodedString.split("\\:");
    String userName="kkkkkk";
    String password="qqqqqq";
    if (s!=null && s.length==2) {
     userName=s[0];
     password=s[1];
    }
    // 04. Check user & pasword values
    if ("Ximo".equals(userName) && "Dante".equals(password)) noAuth=false;
   }
  }
  // 05. Unauthorized response
  if (noAuth) {
   Response unAuthStatus= Response
    .status(Response.Status.UNAUTHORIZED)
    .entity("User cannot access the resource")
    .build();
 
   // 06. Abort the request
   requestContext.abortWith(unAuthStatus);
  } 
 } 
}


In order to execute this code, we should deactivate other filters that we have created before or else we can get into trouble.

If we run the code we get no success as we haven't provided user and password.



But from Postman we can











Comentarios

Entradas populares de este blog

04. MessageBodyReaders and MessageBodyWriters. Custom Media Types

03. Param annotations, and param converters

01. Let's go! Creating a Java Project