Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How to Create a Kotlin App and Secure it Using JSON Web Tokens (Part 1)

DZone's Guide to

How to Create a Kotlin App and Secure it Using JSON Web Tokens (Part 1)

Kotlin is a statically typed, JVM-friendly programming language. We'll use it to create a simple web app, then handle communication security using JSON Web Tokens.

· Java Zone
Free Resource

What every Java engineer should know about microservices: Reactive Microservices Architecture.  Brought to you in partnership with Lightbend.

In this article, we’ll learn how to create a simple application using Kotlin, a statically typed programming language that targets the Java Virtual Machine (JVM). We’ll secure all communication with our application using JSON Web Tokens (JWT’s).

Don’t worry if you don’t know what a JSON Web Token (JWT) is. I’ll cover that in a bit.

And you don’t need to know any Kotlin, either. If you’ve got some decent programming experience with any programming language, you’ll be able to follow through without any difficulty. If you’re a Java programmer, though, you’ll feel right at home because Kotlin uses the Java API to do everything. It’s got a very sparse syntax with a lightweight standard library.

In fact, let us cover all of the features of Kotlin used in the code that goes with this article.

A Crash Course in Kotlin

To declare a variable that can be read from and written to, use the var keyword:

var name : String = “Joe Bloggs”;

var age = 20; // Type inferred by the compiler

age = 21; // valid statement since the variable is writable also

Semi-colons as statement terminators are optional. But it’s a good practice to have them, anyway. All throughout our code, we’ll use semi-colons to terminate statements.

To declare a read-only variable that can only be initialized once, use the val keyword:

val name : String = “Joe Bloggs”;

val age = 20;

age = 21; // Illegal statement. Compiler error. The variable is read-only.

To create a class:

class Student() {
  // This is a class that has one default parameterless constructor
  // The parenthesis after the class name is actually the constructor declaration for this class.
}

class Student {
  // If the class has just one default parameterless constructor, 
  // the parenthesis area optional
}

class Student; // if the class is empty, the curlies are optional.

To create an object of the Student class:

// Kotlin does not have the new keyword. 
// This creates a read-only / assign-once 
// variable of type Student.
val student : Student = Student();

val student = Student(); // type inferred

// read-write variable
var student : Student = Student();

As for nullable types, Kotlin distinguishes between nullable and non-nullable types. Each type, whether a primitive or user defined, has both a nullable version and a non-nullable version. You create a nullable version by appending a question mark (?) after the type name.

var age : Int? = 2; // nullable integer

age = null; // valid

val joe : Student? = null; // valid

var lisa : Student = null; // illegal. Compiler error. The variable is not nullable.

To declare a class Student with a read-only, non-nullable property called name and a read-write, nullable property called age:

class Student(val name : String, var age : Int?);

In the above code, name and age are properties. Kotlin creates a getter for the name property and a getter and setter pair for the age property. Also, the Student class in the listing above gets a parameterized constructor.

To create an object of the Student class and use it:

// creates a read-only, nullable variable of type Student
val student : Student? = Student(“Lisa”, null); 

To create a class with optional parameters in its constructor:

class Student(val name : String, var age : Int? = null, var gender : String = “Male”);

// optional argument omitted. Nullable student.
val joe : Student? = Student(“Joe Bloggs”, 20);

// Provided an explicit value for all 
// arguments including the optional argument. 
// Non-nullable student.
val lisa : Student = Student(“Lisa Hendricks”, 18, “Female”);

Functions in Kotlin can exist independently outside of any class. To create a function that returns void (Unit is a type that means void):

fun Print(name : String?) : Unit {
  if (name != null) {
    println(name);
  }
}

The Unit keyword is optional. The same function could be re-written as the following:

fun Print(name : String?) {
  if (name != null) {
    println(name);
  }
}

To create a class with instance methods:

class Student(val name : String) {

    fun displayName() {
        println(this.name);
    }
}

To use it:

val joe : Student = Student(“Joe Bloggs”);

joe.displayName();

Kotlin does not have static classes. Because functions can exist independent of classes, you just write your functions that you would have wanted to write in a static class in a separate file.

// file: JustMyFunctions.kt

fun play() {
}

fun stop() {
}

fun sing(song : String) {
}

fun fastForward(frames : Int) : Boolean {
}

Sometimes, you want to create a class with no methods just to hold data so you can serialize/deserialize it or just hold some data in it so as to pass that data across the boundaries of your application. Such classes are referred to by various names, such as Data Transfer Objects, data objects, beans, Plain Old Java Objects (POJOs), or Plain Old CLR Objects (POCOs) in the case of C# and .NET.

To create a class of that kind, you’ll simply add the keyword data before the class keyword like so:

data class Student(val name : String) {
  // A class with one read-only, 
  // non-nullable property that has 
  // only a getter for its name property
}

When you create a data class, in addition to the getters and setters for properties, which Kotlin creates even for classes that are not marked as data classes, Kotlin generates the following methods for the data class behind the scenes:

hashCode();

toString();

equals();

copy();

Annotations: You can annotate a method, constructor, or class like in any other language:

@annotationForClass class 
      @annotationForConstructor Student(@propertyAnnotation val name : String) {

    @methodAnnotation fun display() {
        //
    }
}

All classes and methods in Kotlin are non-inheritable and non-overridable, respectively, unless otherwise explicitly stated by declaring them with the open keyword.

class ThisClassCannotBeInherited;

open class ThisClassCan;

open class ThisClassCanAlsoBeInherited {

  fun thisMethodCannotBeOverriden() {
  }

  open fun thisMethodCan() {
  }
}

class ChildClass : ThisClassCanAlsoBeInherited {

  override fun thisMethodCan() {
  }
}

Interfaces and class inheritance:

interface IPerson {
}

open class Person : IPerson {
}

interface ILoggable {
}

open class Student : Person, IPerson, ILoggable {
}

In Kotlin, packages and Visibility Modifiers work exactly like they do in Java.

To create a Singleton object:

object IAmASingletonObject {

  val firstProperty : String;
}

The above construct is called an object declaration. An object declaration is an object instance that does not belong to a class. And since that’s the only instance you can have of it, it is effectively a singleton object. Therefore, you use an object declaration when you need to create a singleton instance.

We use the object declaration like so:

IAmASingletonObject.firstProperty = “Hello, World!”;

You can put it inside a class, as well. In this case, the object will be able to access the internals of its containing class.

If you mark an object declaration with the companion keyword, the members of the companion object can be referenced directly as members of the containing class like so:

class User(val userName : String,  val password : String?) {

  companion object Validator {

    public fun isValid() : Boolean {

      // access containing object’s members
      If (userName.equals(“Joe”) {
    //
      }
    }
  }
}

// Usage

val user : User = getUser();

if (user.isValid()) {
}

That’s pretty much all you need to know to get started and be productive with Kotlin.

What We’re Going to Develop

We’ll create a client/server application that gets from a web API a list of book recommendations for a logged-in user based on the user’s interests or likes. We’ll store the user’s likes in a database.

We’ll write both the client and the web API in Kotlin. The client will be a desktop application written using the Swing/AWT libraries. The server is an HTTP Servlet that returns data objects declared in a library named Contracts as JSON strings. We’ll call our application—in fact, we’ll call this whole system—by the name Bookyard.

Here’s what the high-level component architecture for Bookyard would look like:

Image title

Workflow

Assuming the servlet application is running, when the user launches the client application, a login dialog will appear.

Bookyard Login Dialog

A successful login will dismiss the login dialog and display a window listing the recommended books for the logged-in user.

Book Recommendations Window

Please ignore the aesthetical anomalies of the graphical user interface.

OAuth 2.0 and Token /Claims Based Authorization

In order to understand how we’ll ensure secured communication between the client and the server of Bookyard, I’d like to provide a to-a-four-year-old explanation of some of the highfalutin terms popularly used in elite architect circles.

Consider a traditional web application that resides on a single server. That’s how it used to be done in the old days when the Web was a new thing—you had all the source code on a single server.

You had two parties:

  1. A web server that had some server-side code that ran on the remote server and also some client-side code that ran on the browser.

    Since both the client code and the server code were part of a single application usually written by a single developer or company, the server-side code and the client-side code could be considered a single entity or a single application.

  2. The user using the application in a Web browser.

In those cases, a simple user name and password-based authentication was sufficient to validate the identity of the user. When the user logged in, the server would issue a session ID and an authentication cookie to the user’s browser. The browser would carry these two with every subsequent request to the server.

This all worked fine until the number of users outgrew the server’s capacity to handle requests.

Scenario 1: A Clustered Environment

When you had two servers running the same application code, you had a problem. If the login request came to server A, which issued a session cookie and an authentication cookie to the user, server B didn’t know anything about those cookies. Therefore, any subsequent requests coming in to server B even after the user had innocently validated his identity earlier with server A, would fail with server B.

One obvious solution to this problem is to make server A and server B share their session IDs. This could be done by having an external state server that held the session state for the entire Web application in an external data source, such as a database or an in-memory state server.

A similar but simpler and more secure solution, however, is to have a separate authentication server. Each request that comes to either of the servers—A or B—is validated for the presence of a special value in the request header—a value that could only have been obtained from the authentication server. If the value is present, the servers A or B service the request. If, however, the special value is missing, the client gets redirected to the authentication server, which, after logging the user in, issues this special value that represents a successful login and an active session. Let’s call this value returned by the authentication server an authentication token.

Below is a diagrammatic representation of this simple sequence of three interactions.

Simple Authentication Server Workflow -- Step 1

Under this regime, when the user sends in a request to either of the servers (A or B), each of them checks to see whether the user has an authentication token or not. If he doesn’t, they redirect his request to the authorization server, whose duty is to ask the user for his user name and password, authenticate his identity, and issue him an authentication token upon successful login.

Simple Authentication Server Workflow -- Step 2

The user’s request is then redirected automatically back to the original URL he intended to get the data from-i.e., one of server A or server B. This time, his request carries with it the token, so either of the servers fulfills his request.

Simple Authentication Server Workflow -- Step 3

This scheme of authentication and authorization is known as token-based authentication or token-based authorization. A series of steps performed in a sequence, as indicated above, may also be called a workflow. Let us name this particular workflow the Simple Authentication Server Workflow.

I’d like to confess that the names authentication token and Simple Authentication Server Workflow are names I have made up. You will not find them in security literature. But in deliberately flying by the seat of my pants on good accord, I am trying to avoid trespassing names that already occur in security literature with specific connotations. If I named this token an access token, for example, or if I named the series of steps described above as Authorization Workflow, I’d be trespassing a commonly accepted nomenclature that we’ll make a nodding acquaintance with later in this article.

The above series of steps, though potent as a basic building block for more specialized variants, is rather simplistic in that it does not describe the contents of the token and ways of securing it against theft. In practice, how we name such a token is predicated on such puritanical considerations.

Token Uses and Composition

In our simple example, the client application is a Web application that serves a list of book recommendations for a user based on the user’s likes. The authentication server is a separate endpoint that could be a part of the same application or a different one. The simplicity, however, is born of an assumption that both the authentication server and the resource servers are developed by the same vendor.

Because both the authentication server and the resource servers are assumed to either be a part of the same Web application or—at worst—be URLs of two Web applications developed by the same vendor, the use of such a token was both to authenticate a user and consequently to authorize him for access to the data held in the resource servers.

The evolution of the Web in recent times has opened up a slew of interesting possibilities that call for variations on the workflow described above.

Authentication

Big players, such as Google, Yahoo!, and Facebook (to name a few) command large user bases of the total Internet population. This has encouraged users and Web application developers to trust these big players to authenticate users for their identity, consequently freeing up Web application developers to concentrate on developing just business logic, delegating the authentication of their users to these giants.

Imagine building a job search portal. You need to validate that the user is above 18 years of age and has a valid social security number. You don’t really care about any other information about the user. In this case, you could use the US government website to validate the user against these two parameters and receive a token containing identification information about the user. This specific need for authenticating a user’s identity dictates what the contents of the token will be.

Authorization

Another use that has come to light is the sharing of data from one Web application to another. Imagine yourself developing a photo editing software for your users. Instead of having users upload pictures to your Web server, you could pull out their pictures from their Flickr accounts, edit them in your application, and save them to the user’s dropbox or back to their Flickr accounts. In this case, you don’t care about the user’s identity as much as you care about their permission to use their Flickr photographs and their dropbox account.

Both the above uses—namely, the authentication and authorization of users—dictate the separation of the server granting the token, the role of such a token, and consequently its contents.

Though OAuth 2.0 access tokens are opaque strings, the authorization server may, upon request, attach additional information about a user, such as his full name, email address, organization, designation, and what have you into the token container. Such a workflow is illustrated by a variation named Open ID Connect, which builds on top of the OAuth 2.0 framework. This token would then be called an ID token. This would obviate the necessity for a database look-up. If such information were to be required by either of the servers (A or B), they could simply read it from the ID token itself without making a trip to the database server. Each such optional datum attached to an access token is known as a claim, as it establishes a claim upon the identity of the user. For this reason, token-based authentication is also referred to as claims-based authentication.

The client or server may communicate using tokens even when their dialog does not pertain to authentication or authorization. With each request, the client may package the information it needs to send to the server in the form of a token, although it wouldn’t be called an access token in that case. You’ll observe later that the login dialog of Bookyard Client sends the user’s username and password in such a token when making a login request to the Bookyard server. That is an example usage of a token of this type but not for the purposes of behaving like an access token.

Scenario 2: The Distributed Web and OAuth 2.0

This mechanism of claims-based authorization described in the above paragraphs has opened up the Web to new possibilities. Consider a scenario where you needed to import your Gmail contacts into LinkedIn so you can invite them all to join your Linked In network.

Until 2007, you couldn’t have done that without having your arm twisted. The only way to do that would have been for Linked In to present you with a screen wherein you typed your Gmail username and password into a Linked In user interface, effectively giving Linked In your Gmail username and password. What a shoddy life our younger selves lived!

Thankfully, a bunch of guys at Twitter got together and said, “That must change.”

They started by identifying that in a transaction of the kind described above, there are three parties involved:

  1. A resource server: A server where the user’s data is kept. In this case, that would be Gmail because your contacts would be kept there.
  2. A user who owned the resources at Gmail; and
  3. A client: A third-party application that needed access to your data from the resource server. In other words, Linked In (the third party) that needed your Gmail (resource server) contacts.

They wrote out a bunch of rules that both the resource server (Gmail in this example) and the third-party application (Linked In in this example) would have to incorporate into their code in order to perform claims-based authorization so that you wouldn’t have to give your Gmail username and password to Linked In.

They called this grand scheme of interaction OAuth. It has since spread like wildfire.

OAuth has, since its advent, been revised twice as v1, v1a and v2.0. Version 2.0 is the most recent and popular one, and the versions are not backward compatible. Any reference to OAuth in this article without an explicit version suffix must be understood to mean OAuth 2.0.

Today, virtually every website—from GitHub to Gmail, Picassa, to Flickr, and perhaps even your own company’s—has a resource server that exposes data in an OAuth way. The OAuth 2.0 specification also calls resource servers by the name OAuth servers, and the third-party clients by the name OAuth clients.

Today, virtually every user, knowingly or not, uses OAuth. Wherever on the Web you see buttons of the kind below, that is OAuth 2.0 in action.

Login with Facebook

Login with Github

Import Linked In profile

The evolution of the Web has enabled a scenario where the traditional web application could be written by an OAuth provider. The client application, as was the case with LinkedIn in our example above, could be written by someone else, and the user could be someone else.

OAuth 2.0 access tokens are opaque and can be any string—even the string “Hello, World!” But such a value offers no security. In practice, an access token is a bit more useful than “Hello, World,” as it carries an expiry timestamp and may even be encrypted using symmetric or asymmetric encryption.

With that brief explanation out of the way, next time, we'll dive into JSON Web Tokens and how they can be used to secure communications in your newly created Kotlin app.

Microservices for Java, explained. Revitalize your legacy systems (and your career) with Reactive Microservices Architecture, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:
web application ,json web token ,java ,kotlin ,tutorial

Published at DZone with permission of Sathyaish Chakravarthy, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}