0% found this document useful (0 votes)
68 views32 pages

SSL and Token Authentication Tutorial

This tutorial focuses on API authentication using JSON web tokens and adding HTTPS security with a self-signed SSL certificate. It discusses implementing token-based authentication in a UserRest API and validating tokens in requests to a modified CustomerRestForm API. The tutorial also covers using the Postman API client to test the applications by creating collections and environments.

Uploaded by

Brent Liang
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
68 views32 pages

SSL and Token Authentication Tutorial

This tutorial focuses on API authentication using JSON web tokens and adding HTTPS security with a self-signed SSL certificate. It discusses implementing token-based authentication in a UserRest API and validating tokens in requests to a modified CustomerRestForm API. The tutorial also covers using the Postman API client to test the applications by creating collections and environments.

Uploaded by

Brent Liang
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 32

Tutorial 8 – Security

and Authentication

SOEN 487 - Web Services and Applications


By: Konstantinos Psimoulis
Introduction

This tutorial will focus on the following two key tasks for web security:

● API authentication using a Token.

● Adding a self signed certificate to provide HTTPS for our service.

Winter 2021
Token Authentication

Token-based authentication is a protocol which allows users to verify their identity, and in
return receive a unique access token.

This token can then be sent to the API with every request, avoiding the need to send our
credentials every single time.

Winter 2021
SSL Certificate

SSL stands for Secure Sockets Layer and, in short,


it's the standard technology for keeping an
internet connection secure and safeguarding any
sensitive data that is being sent between two
systems. It does so by creating an encrypted link
between you and the server.

When a website is using HTTPS and is showing up


as secured, it is essentially using an SSL certificate
which is trusted by the browser/client you are
using.

Winter 2021
SSL Certificate

Usually, SSL certificates have an expiration date, which varies depending on the issuer,
meaning that they need to be renewed every so often. Thus you always need to keep an
eye on the certificate duration when deploying on a server.

More info: Here

Also, simply adding an SSL certificate does not guarantee that the web server is completely
secure. The server also needs to be properly configured to ensure that security standards
are being met. Qualys provides an excellent tool to check whether a website is secure or
not.

Link: Here

Winter 2021
SSL Certificate

There are a few ways for the security to be compromised at all stages of the connection.

Winter 2021
Restaurant API from T03

We will be using the CustomerRest implementations from T03 for this Tutorial as well,
with some slight modifications

Winter 2021
Postman

Postman is an API client that makes creating, sharing and testing APIs very fast and easy.

We will be using Postman for this tutorial, specifically how to create and utilize Collections and
Environments.

Winter 2021
Changes from T03

The initial repo for this tutorial adds three new classes, which will be used in our
implementation.

● User.java
● MyResponse.java
● UserRest.java

The User class is a POJO similar to the customer, which will be used as the base for our
authentication server users.

MyResponse is used as a simple data structure to simplify reading the token after login (more on
this on the next slides).

UserRest holds the implementation for our authentication service.

Winter 2021
UserRest

The following four functions have been implemented:

● createUser
● login
● logout
● validateToken

We are using two hash maps to store the token information, but this can be done in many other
ways. validateToken checks if the token sent exists in our data structures and then checks how
long ago it was created.

Winter 2021
validateToken

Here is the implementation for this method:

@POST
@Path("/auth")
public Response validateToken(@HeaderParam("x-api-key") String token) {
if(tokenUsername.containsKey(token)){
Date timeNow = new Date();
long diff = timeNow.getTime() - tokenExpiration.get(token).getTime();
long tokenDuration = TimeUnit.MILLISECONDS.toMinutes(diff);
System.out.println("Duration: " + tokenDuration);
if(tokenDuration > 30){
tokenUsername.remove(token);
tokenExpiration.remove(token);
}
else{
return Response.status(Response.Status.OK).entity("true").build();
}
}
return Response.status(Response.Status.UNAUTHORIZED).entity("false").build();
}

Winter 2021
validateToken

Note the following annotation in the method input variables:

@HeaderParam("x-api-key")

This means that when sending the request to validate the token, we need to include a header
called x-api-key containing the generated token.

Winter 2021
CustomerRestForm

We will now edit the methods that alter the data of the CustomerRestForm API to require
token authentication.

We will also need a method to send a POST request to the authentication service. This way,
when a request is sent to edit the API data, it will have to be accompanied with a valid token,
otherwise it will fail.

Winter 2021
CustomerRestForm

validateToken method:

private boolean validateToken(String token) {


try (CloseableHttpClient client = HttpClients.createDefault()) {
HttpPost httpPost = new HttpPost(String.format("http://localhost:8080/restaurant/user/auth"));
httpPost.addHeader("x-api-key", token);
CloseableHttpResponse httpResponse = client.execute(httpPost);
HttpEntity entity = httpResponse.getEntity();
String isAuthenticated = EntityUtils.toString(entity);
httpResponse.close();
if(isAuthenticated.equals("true")){
return true;
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}

Winter 2021
CustomerRestForm

createCustomer method:

@POST
public Response createCustomer(@HeaderParam("x-api-key") String token,
@FormParam("name") String name, @FormParam("age") int age {
if(validateToken(token)){
Customer newCustomer = new Customer(name, age);
customers.add(newCustomer);
return Response.status(Response.Status.OK).entity("Succesfully added user!").build();
}
return Response.status(Response.Status.UNAUTHORIZED).entity("User not authenticated!").build();
}

Similarly, the modifyCustomer and deleteCustomer methods need to be altered as well.

Winter 2021
CustomerRestForm

modifyCustomer method:
@PUT
@Path("{id}")
public Response modifyCustomer(@HeaderParam("x-api-key") String token,
@PathParam("id") int id, @FormParam("name") String name, @FormParam("age") int age) {
if(validateToken(token)){
Customer customer = customers.stream().filter(customer1 -> customer1.getId() == id)
.findFirst()
.orElse(null);
if(customer != null){
customer.setAge(age);
customer.setName(name);
return Response.status(Response.Status.OK).entity("Succesfully modified customer!").build();
}
else{
return Response.status(Response.Status.OK).entity("Customer does not exist!").build();
}
}
return Response.status(Response.Status.UNAUTHORIZED).entity("User not authenticated!").build();
}

Winter 2021
CustomerRestForm

deleteCustomer method:

@DELETE
@Path("{id}")
public Response deleteCustomer(@HeaderParam("x-api-key") String token, @PathParam("id") int id) {
if(validateToken(token)){
customers = customers.stream().filter(customer -> customer.getId() != id)
.collect(Collectors.toCollection(ArrayList::new));
return Response.status(Response.Status.OK).entity("Succesfully deleted customer!").build();
}
return Response.status(Response.Status.UNAUTHORIZED).entity("User not authenticated!").build();
}

Winter 2021
Creating a Postman Collection

To create a postman collection, simply click on New from the Scratch Pad or Workspace on the
top left and select Collection.

Winter 2021
Creating a Postman Collection

You can then name your collection and start adding requests. You should also create an
Environment which will hold important variables.

Winter 2021
Import Postman Collection

To import a postman collection, simply click on File -> Import and upload the collection file
included in the repository.

Winter 2021
Postman Environment

If you import the postman collection, make sure that the variables in your environment match
the ones in the collection.

Winter 2021
Testing with Postman

You can now run the application from the main() method in IntelliJ and create/add the existing
commands in Postman.

Adding a customer should now not be working without the token but getting the customers
should function as before.

Winter 2021
Adding SSL for HTTPS

In this case, generating SSL keys and implementing HTTPS is fairly simple. In the project
directory, open Git Bash and run the following command:

keytool -genkey -keyalg RSA -keystore localhost.jks -alias localhost -ext SAN=dns:localhost

Note: When asked for passwords enter changeit, since that is what we used in our case.

After adding the password the guide will ask you to enter first name, last name etc. These are
useful for identifying where the certificate is from but in our case you can enter anything, as we
will only be using them locally.

Important Note: You can swap localhost in the command to any domain name you want, but
make sure you use the same one in the code and the requests. (More on slide 24)

Winter 2021
Adding SSL for HTTPS

After the localhost.jks has been generated, run the following two commands:

keytool -importkeystore -srckeystore localhost.jks -destkeystore localhost.p12 -srcstoretype JKS -


deststoretype PKCS12 -srcstorepass changeit -deststorepass changeit -srcalias localhost -destalias
localhost -srckeypass changeit -destkeypass changeit

Gitbash (Win): winpty openssl pkcs12 -in localhost.p12 -clcerts -nokeys -out localhost.crt
MacOS: openssl pkcs12 -in localhost.p12 -clcerts -nokeys -out localhost.crt

The localhost.p12 file will help us add the certificate to Chrome, while localhost.crt will be used
with curl.

Winter 2021
Java SSL Changes

Before continuing, we need to make a few changes to the Java code. First add the following lines
in the validateToken method in CustomerRestForm:

private boolean validateToken(String token) {


// Setting the truststore to our server.jks file let Java trust the certificate.
System.setProperty("javax.net.debug", "ssl");
System.setProperty("javax.net.ssl.trustStore",“localhost.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

We are adding the certificate generated to Java’s trust store, to make sure the SSL handshake
works properly. Also change all hardcoded URLs in the code to include https and change the
port to 8443.

Winter 2021
Java SSL Changes

Similarly, we need to make some changes in the Main method, to actually create an https server.
Change the base URI and add the two following variables:

public static final String BASE_URI = "https://0.0.0.0:8443/restaurant/";


private static final String KEYSTORE_LOC = “localhost.jks";
private static final String KEYSTORE_PASS = "changeit";

Notice that we change the URI to be 0.0.0.0 instead of localhost.

Winter 2021
Java SSL Changes

Finally, update the startServer() method:

public static HttpServer startServer() {


// create a resource config that scans for JAX-RS resources and providers
// in com.example.rest package
final ResourceConfig rc = new ResourceConfig().packages("com.example.rest");
rc.register(MultiPartFeature.class);

SSLContextConfigurator sslCon = new SSLContextConfigurator();


sslCon.setKeyStoreFile(KEYSTORE_LOC);
sslCon.setKeyStorePass(KEYSTORE_PASS);

// create and start a new instance of grizzly http server


// exposing the Jersey application at BASE_URI
return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc,
true, new SSLEngineConfigurator(sslCon).setClientMode(false).setNeedClientAuth(false));
}

You can now run the server again and it should run on https.

Winter 2021
Adding Certificate to Chrome

In Google Chrome, go to Settings, type SSL in the search bar, click on Security and then Manage
Certificates.

Click on the Trusted Root Certification Authorities tab and then Import. Follow the guide and
use the .p12 file when prompted.

Winter 2021
Connecting with HTTPS

You should be able to visit the following URL on Chrome and see the site as secured.

https://localhost:8443/restaurant/customerform

You can also run the following curl command from the project directory to check that https is
working properly:

curl --cacert localhost.crt https://localhost:8443/restaurant/customerform

Winter 2021
Postman with HTTPS

Postman does not allow self signed certificates like


the one we made, and so we need to turn SSL
certificate validation off to use the web service. You
can find the setting in File ->Settings.

Change the app url in the Environment to https and


you should be good to go.

Winter 2021
Custom domain name

To use a custom domain name for our web service, we can run the keytool commands again and change
localhost to the name we want (e.g. restaurant.local).

We then need to edit the hosts file as admin (C:\Windows\System32\drivers\etc\hosts in windows) and
add a line to redirect restaurant.local to localhost like follows:

127.0.0.1 restaurant.local

On Linux and MacOS you can edit the file with the following command:

sudo nano /etc/hosts

Follow the same steps again to change the URLs and add the cerificate to Chrome, and you should then
be able to visit the site securely with the custom name.

Winter 2021
References

- Token-Based Authentication
- SSL, TLS and HTTPS
- Qualys SSL Test
- Token Image
- SSL Image
- Postman Logo

Winter 2021

You might also like