How to generate JWT token in Android?

I would like to use Cloud API in my android application. I am stuck how can I get the public and private key from my account and generate self-signed JWT token.

Any sample code would be appreciated here.

Hi Sandeep,

You get the private key when you create a cloud app (https://poynt.net/cloudapps/add) or upload an Android app (https://poynt.net/terminalapps/add) on poynt.net.

Here’s sample code on how to generate JWT using your app id and private key.

package co.poynt.samples;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.OutputStream;
import javax.net.ssl.HttpsURLConnection;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.Security;
import java.security.interfaces.RSAPrivateKey;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;


/*
 * DISCLAIMER OF WARRANTY
 * 
 * This source code is provided "as is" and without warranties as to performance or merchantability. 
 * This source code is provided without any express or implied warranties whatsoever. 
 * Because of the diversity of conditions and hardware under which this source code may be used, 
 * no warranty of fitness for a particular purpose is offered. 
 * The user is advised to test the source code thoroughly before relying on it. 
 * The user must assume the entire risk of using the source code.
 */
public class Poynt{
	// TODO copy your application id starting with urn:aid here
	private static String applicationId = "<your app id>";
	// private key downloaded from poynt.net
	private static String privateKeyFile = "src/privateKey.pem";
	private static String apiEndpoint = "https://services.poynt.net";

	private static String getJWT() throws Exception{
		File f = new File(privateKeyFile);
		InputStreamReader isr = new InputStreamReader(new FileInputStream(f));
		
		PEMParser pemParser = new PEMParser(isr);
		Object object = pemParser.readObject();
		PEMKeyPair kp = (PEMKeyPair) object;
		Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
		JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
		RSAPrivateKey privateKey = (RSAPrivateKey) converter.getPrivateKey(kp.getPrivateKeyInfo());
		pemParser.close();
		
		// Create RSA-signer with the private key
		JWSSigner signer = new RSASSASigner(privateKey);
		
		// Prepare JWT with claims set
		JWTClaimsSet claimsSet = new JWTClaimsSet();
		claimsSet.setSubject(applicationId);
		claimsSet.setAudience(Arrays.asList(apiEndpoint));
		claimsSet.setIssuer(applicationId);
		claimsSet.setExpirationTime(new Date(new Date().getTime() + 360 * 1000));
		claimsSet.setIssueTime(new Date(new Date().getTime()));
		claimsSet.setJWTID(UUID.randomUUID().toString());
		
		SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.RS256), claimsSet);
		
		// Compute the RSA signature
		signedJWT.sign(signer);
		
		String s = signedJWT.serialize();
		return s;
	}

	public static String getAccessToken() throws Exception{

		URL url = new URL(apiEndpoint + "/token");
		HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
		conn.setDoOutput(true);
		conn.setRequestMethod("POST");
		conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
		conn.setRequestProperty("api-version", "1.2");
		conn.setRequestProperty("Poynt-Request-Id", UUID.randomUUID().toString());

		String postData = "grantType=urn:ietf:params:oauth:grant-type:jwt-bearer";
		postData += "&assertion=" + getJWT();
		OutputStream os = conn.getOutputStream();
		os.write(postData.getBytes());
		os.flush();

		if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
			throw new RuntimeException("Failed : HTTP error code : "
				+ conn.getResponseCode());
		}

		BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
		String response  = br.readLine();
		conn.disconnect();

		ObjectMapper mapper = new ObjectMapper();
		Map<?,?> map  = mapper.readValue(response, Map.class);
		return (String)map.get("accessToken");			
	}
}
1 Like

Hi Sandeep,

Let me clarifying something important. You should NOT be calling cloud APIs directly from your Android app, instead use PoyntSDK interface. The code snippet above is suitable only for developing a cloud application to call Poynt REST API.

If you find that you are not able to do something using the PoyntOS SDK interface please let us know.

1 Like

Thanks deniis .is there any disadvantage if I call Cloud API directly from my Androud app to get the details from my poynt account? I will explore the poynt SDK. I tried to run your sample app but it is crashing on device.

For one, you should not be generating the JWT on the device because it requires a private key, and you should not be bundling your private key with your app. By calling the SDK you are also keeping things in synch between the cloud and the terminal. Otherwise it may take up to an hour to synch the data.

Regarding the sample app crash, an you post the error from the logs?

1 Like

Thanks dennis. I will get back to you.

Once I click on CurrentUser button, It is giving nullpointException with below code

`05-26 11:19:20.636 22094-22094/co.poynt.samples D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
05-26 11:19:20.806 22094-22094/co.poynt.samples D/TransactionTestActivity: Exception received: bind failure
05-26 11:19:29.476 22094-22094/co.poynt.samples D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
05-26 11:19:29.556 22094-22094/co.poynt.samples D/AndroidRuntime: Shutting down VM
05-26 11:19:29.556 22094-22094/co.poynt.samples W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x41c48da0)
05-26 11:19:29.566 22094-22094/co.poynt.samples E/AndroidRuntime: FATAL EXCEPTION: main
Process: co.poynt.samples, PID: 22094
java.lang.NullPointerException
at co.poynt.samples.SampleActivity$2.onClick(SampleActivity.java:98)
at android.view.View.performClick(View.java:4809)
at android.view.View$PerformClick.run(View.java:19660)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5756)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(Native Method)
05-26 11:19:31.896 22094-22094/co.poynt.samples I/Process: Sending signal. PID: 22094 SIG: 9

I am running this example on my Samsung galaxy device with 4.4.4 version.
`

Hi Dennis,

I downloaded the sample code and imported in Android studio and compiled and build it. I can see that sample app is not able to bind with any service and when I am clicking on getAuthToken button, it is not showing the Login screen or getting the token. I checked the SDK classes and I can’t see AccountAuthenticatorActivity and AccountAuthenticator.

I would like to customize the login screen or sign up screen so I assume I need to overide the poynt AccountAuthenticatorActivity but coun’t find any reference of it.

Do I need to do something before running the sample code as it is not binding with the services?

Do we have any API in SDK to create a account from Android SDK rather than creating on poynt server?

Waiting for your response.

Best
Sandeep Agrawal
labs108 inc

Can you connect to your tablet over adb and run:

adb shell pm list packages | grep -i poynt

Also can you post your source code somewhere and email me the link at dennis@poynt.com?

Hi Dennis,

I was trying to run the app on my personal Android device so it was not working. Once I ran it on poynt simulator, it start working.

Best
Sandeep

I cannot find my private key. I only find Public key.
And more, I don’t understand cloud API for InAppBilling. I need it? or can I just handle it from callback in my App?