Using Kinde without an SDK
SDKs and APIs
The Kinde Java SDK allows developers to connect their Java app to Kinde.
You can find our Java SDK and Java starter kit in GitHub.
The SDK is officially only supported for Java version 17 or later.
If you haven’t already created a Kinde account, register for free here. Registration gives you a Kinde domain, which you will need to get started. e.g. yourapp.kinde.com
.
If you’re using version 1, see Java SDK v1
The Kinde Java core provides the core of the Kinde SDK for the Java platform. This is necessary to install for connecting to Kinde.
Clone the SDK repository.
git clone https://github.com/kinde-oss/kinde-java-sdk.git
Create a JAR file of your SDK project using the below command:
cd kinde-java-sdkmvn clean install
Kinde’s SDK is available through Maven. To install it, add the following line to your pom.xml
.
<dependency> <groupId>com.kinde</groupId> <artifactId>java-sdk</artifactId> <version>[2.0.1,)</version></dependency>
Add this dependency to your project’s build file:
repositories { mavenCentral() // Needed if the ‘kinde’ jar has been published to maven central. mavenLocal() // Needed if the ‘kinda’ jar has been published to the local maven repo. }
dependencies { implementation "com.kinde:java-sdk:+” }
The following environment variables are required for connecting to Kinde. This will enable the development of a M2M client service.
export KINDE_DOMAIN=https://<replace>.kinde.com # This is the domain you setup at kindeexport KINDE_CLIENT_ID=<replace> # the id for the client connecting to Kindeexport KINDE_CLIENT_SECRET=<replace> # the secret used to authenticate the client against Kinde
Provide a redirect URI, so a user’s login can be validated against Kinde.
export KINDE_REDIRECT_URI=http://localhost:8080/kinde-j2ee-app/login
The redirect URI/URL is used post successful login. It is the URL that the PKCE client CODE will be set to. A query parameter of ?code=‘value’ must be processed.
The Kinde library supports .env files. The must be located in the directory from which the application is executed.
KINDE_DOMAIN=https://<replace>.kinde.comKINDE_CLIENT_ID=<replace>KINDE_CLIENT_SECRET=<replace>KINDE_REDIRECT_URI=http://localhost:8080/kinde-j2ee-app/login
To make a M2M server token request onto Kinde, set up the environment variables.
Run these exports before running your service.
export KINDE_DOMAIN=https://<replace>.kinde.com # This is the domain you setup at kindeexport KINDE_CLIENT_ID=<replace> # the id for the client connecting to Kindeexport KINDE_CLIENT_SECRET=<replace> # the secret used to authenticate the client against Kinde
Place this .env file in the directory from which you run your service.
KINDE_DOMAIN=https://<replace>.kinde.comKINDE_CLIENT_ID=<replace>KINDE_CLIENT_SECRET=<replace>
If you want to pass in configuration programmatically, use the KindeClientBuilder
.
KindeClient kindeClient = KindeClientBuilder .builder() .domain("<replace>") .clientId("<replace>") .clientSecret("<replace>") .build();
The example below details how to implement a server-level token request. This is needed for M2M communication and authorization.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeClientSession kindeClientSession = kindeClient.clientSession();KindeTokens tokens = kindeClientSession.retrieveTokens();
To authenticate a user on the client-side, configure as follows.
Run these exports before running your service.
export KINDE_DOMAIN=https://<replace>.kinde.com # This is the domain you setup at kindeexport KINDE_CLIENT_ID=<replace> # the id for the client connecting to Kindeexport KINDE_CLIENT_SECRET=<replace> # the secret used to authenticate the client against Kindeexport KINDE_REDIRECT_URI=openid # the open id
Place this .env file in the directory from which you run your service.
KINDE_DOMAIN=https://<replace>.kinde.comKINDE_CLIENT_ID=<replace>KINDE_CLIENT_SECRET=<replace>KINDE_REDIRECT_URI=<replace>KINDE_SCOPES=openid
If you want to pass in configuration programmatically, use the KindeClientBuilder
.
KindeClient kindeClient = KindeClientBuilder .builder() .domain("<replace>") .clientId("<replace>") .clientSecret("<replace>") .redirectUri("replace") .addScope("openid") .build();
Before the PKCE code can be processed, a user must be directed to Kinde to sign in. The client library can generate this URL as follows.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeClientSession kindeClientSession = kindeClient.clientSession();AuthorizationUrl authorizationURL = kindeClientSession.authorizationUrl();
The AuthorizationUrl contains the url and CodeVerify information. If using a code grant the code verify needs to be stored for the redirect call. This can be done using the J2EE session. Here is an example
req.getSession().setAttribute("AuthorizationUrl",authorizationUrl);resp.sendRedirect(authorizationUrl.getUrl().toString());
If it is a code auth, then the AuthorizationUrl
needs to be retrieved.
AuthorizationUrl authorizationUrl = (AuthorizationUrl)req.getSession().getAttribute("AuthorizationUrl");
The token request looks like the following.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeTokens tokens = kindeClient.getKindeClient().initClientSession(code,authorizationUrl).retrieveTokens();
It is possible to retrieve user information using an AccessToken. In the example below, an access token is passed in a client session.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeClientSession kindeClientSession = kindeClient.getKindeClient().initClientSession(accessToken);UserInfo userInfo = kindeClientSession.retrieveUserInfo();
Retrieve the user details for the code that has been authenticated.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeClientSession kindeClientSession = kindeClient.getKindeClient().initClientSession(code,authorizationUrl);UserInfo userInfo = kindeClientSession.retrieveUserInfo();
The UserInfo object retrieved above contains the following member variables.
Variables | Description |
---|---|
userInfo | The nimbus user object for more information |
subject | The subject of the user object |
id | The id of the user on Kinde |
givenName | The given or first name of the user |
familyName | The family or surname of the user on Kinde |
The email address of the user on Kinde | |
picture | The picture of the user on Kinde |
login
The login process generates an authorization url. This can be used by the browser to initiate the login on Kinde, and once completed the user will be re-directed back.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeClientSession kindeClientSession = kindeClient.getKindeClient().clientSession();AuthorizationUrl authorizationURL = kindeClientSession.login();
Send the redirect response using:
resp.sendRedirect(authorizationUrl.getUrl().toString());
register
authenticate flowThe register process generates an authorization URL. This URL can be used to redirect the user to Kinde to register, and then redirect them back to complete the PKCE login.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeClientSession kindeClientSession = kindeClient.getKindeClient().clientSession();AuthorizationUrl authorizationURL = kindeClientSession.register();
Send the redirect response using:
resp.sendRedirect(authorizationUrl.getUrl().toString());
logout
The register process generates an authorization URL. This can be used by the browser to initiate the login.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeClientSession kindeClientSession = kindeClient.getKindeClient().clientSession();AuthorizationUrl authorizationURL = kindeClientSession.logout();
Send the redirect response using:
resp.sendRedirect(authorizationUrl.getUrl().toString());
getToken
To complete authentication of a user and retrieve their tokens, do the following.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeTokens tokens = kindeClient.getKindeClient().initClientSession(code,authorizationUrl).retrieveTokens();
Retrieve a client session for the application and then retrieve the tokens for that client.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeTokens tokens = kindeClient.getKindeClient().clientSession().retrieveTokens();
createOrg
authentication flowThe register process generates an authorization URL. This URL can be used to redirect the user to Kinde to register, and then redirect them back to complete the PKCE login.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeClientSession kindeClientSession = kindeClient.getKindeClient().clientSession();AuthorizationUrl authorizationURL = kindeClientSession.createOrg("Org Value");
Send the redirect response using:
resp.sendRedirect(authorizationUrl.getUrl().toString());
getClaim
Claims are available from the tokens.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeTokens tokens = kindeClient.getKindeClient().initClientSession(code,authorizationUrl).retrieveTokens();tokens.getAccessToken().getClaim("key");
The API on the token provides the getClaim
method, which uses a key name to identify the claim in the token, and return the json object it refers to.
getPermission
The permissions are available from the token.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeTokens tokens = kindeClient.getKindeClient().initClientSession(code,authorizationUrl).retrieveTokens();List<String> permissions = new ArrayList<String>();permissions.addAll(tokens.getAccessToken().getPermissions());
getOrganization
The organization can be retrieved from the access token.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeTokens tokens = kindeClient.getKindeClient().initClientSession(code,authorizationUrl).retrieveTokens();List<String> organizations = new ArrayList<String>();permissions.addAll(tokens.getAccessToken().getOrganizations());
getUserDetails
The user details are available either via the AccessToken or via the OAuth2 user info endpoint. Using the Token API:
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeTokens tokens = kindeClient.getKindeClient().initClientSession(code,authorizationUrl).retrieveTokens();tokens.getAccessToken()... // retrieve user information // username // permissions // claims // feature flags
If this is not sufficient, the OAuth2 user info endpoint can be invoked. This can be done using an access token, or just after code auth. The following scopes ware required, openid, profile, email
.
Using the code-created client:
KindeClientSession kindeClientSession = kindeClient.initClientSession(code, authorizationUrl);UserInfo userInfo = kindeClientSession.retrieveUserInfo();assertNotNull(userInfo);assertNotNull(userInfo.getEmail());assertNotNull(userInfo.getSubject());assertNotNull(userInfo.getId());assertNotNull(userInfo.getPicture());assertNotNull(userInfo.getGivenName());assertNotNull(userInfo.getFamilyName());
Using a token-created client:
KindeClientSession kindeClientSession = kindeClient2.initClientSession(accessToken);UserInfo userInfo = kindeClientSession.retrieveUserInfo();assertNotNull(userInfo);assertNotNull(userInfo.getEmail());assertNotNull(userInfo.getSubject());assertNotNull(userInfo.getId());assertNotNull(userInfo.getPicture());assertNotNull(userInfo.getGivenName());assertNotNull(userInfo.getFamilyName());
getUserOrganizations
The organization can be retrieved from the access token.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeTokens tokens = kindeClient.getKindeClient().initClientSession(code,authorizationUrl).retrieveTokens();List<String> organizations = new ArrayList<String>();organizations.addAll(tokens.getAccessToken.getOrganizations());
getFlags
The flags can be retrieved from the token. Once you have referenced the access token, the getFlag
method can be called. This method returns a Map<String,Object>
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeTokens tokens = kindeClient.getKindeClient().initClientSession(code,authorizationUrl).retrieveTokens();tokens.getAccessToken().getFlags();
getBooleanFlag
This method returns a boolean value of the internal flag value.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeTokens tokens = kindeClient.getKindeClient().initClientSession(code,authorizationUrl).retrieveTokens();tokens.getAccessToken().getBooleanFlag(key);
getStringFlag
This method returns a string value.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeTokens tokens = kindeClient.getKindeClient().initClientSession(code,authorizationUrl).retrieveTokens();tokens.getAccessToken().getStringFlag(key);
getIntegerFlag
The method returns the value for the key in type integer.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeTokens tokens = kindeClient.getKindeClient().initClientSession(code,authorizationUrl).retrieveTokens();tokens.getAccessToken().getIntegerFlag(key);
This is the Kinde J2EE Library, and contains the core components needed to manage a client connection to the Kinde from a J2EE servlet container.
In order to use this SDK include following POM dependency.
<dependency> <groupId>com.kinde</groupId> <artifactId>kinde-j2ee</artifactId> <version>[2.0.1,)</version> </dependency>
In order to use the SDK with a Gradle build process please use the following dependency.
configuration('com.kinde:kinde-j2ee:+')
Configure the web.xml file to use these servlets.
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <servlet> <servlet-name>KindeLoginServlet</servlet-name> <servlet-class>com.kinde.servlet.KindeLoginServlet</servlet-class> </servlet> <servlet> <servlet-name>KindeLogoutServlet</servlet-name> <servlet-class>com.kinde.servlet.KindeLogoutServlet</servlet-class> </servlet> <servlet> <servlet-name>KindeRegisterServlet</servlet-name> <servlet-class>com.kinde.servlet.KindeRegistrationServlet</servlet-class> </servlet> <filter> <filter-name>KindeLoginFilter</filter-name> <filter-class>com.kinde.filter.KindeLoginFilter</filter-class> </filter> <servlet-mapping> <servlet-name>KindeLoginServlet</servlet-name> <url-pattern>/login</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>KindeRegisterServlet</servlet-name> <url-pattern>/register</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>KindeLogoutServlet</servlet-name> <url-pattern>/logout</url-pattern> </servlet-mapping> <filter-mapping> <filter-name>KindeLoginFilter</filter-name> <url-pattern>/private/*</url-pattern> <!-- Apply to all URLs or specify specific patterns --> </filter-mapping></web-app>
The above project configuration sets up an example web.xml using the Kinde-J2EE servlets and filters. These are all you need to secure a J2EE project and can be used with Spring Boot or Quarkus:
Configuration can either be performed by exports or through an .env file.
export KINDE_DOMAIN=https://<replace>.kinde.com # This is the domain you set up at kindeexport KINDE_CLIENT_ID=<replace> # the ID for the client connecting to Kindeexport KINDE_CLIENT_SECRET=<replace> # the secret used to authenticate the client against Kindeexport KINDE_REDIRECT_URI=http://localhost:8080/kinde-j2ee-app/login
The Kinde library supports .env files. The files must be located in the directory from which the application is executed.
KINDE_DOMAIN=https://<replace>.kinde.comKINDE_CLIENT_ID=<replace>KINDE_CLIENT_SECRET=<replace>KINDE_REDIRECT_URI=http://localhost:8080/kinde-j2ee-app/login
The Spring Boot starter manages all the dependencies required by a spring boot application connecting to Kinde.
To use configure Spring Boot to use Kinde for authentication, include the following dependency.
<dependency> <groupId>com.kinde.spring</groupId> <artifactId>kinde-springboot-starter</artifactId> <version>[2.0.1,)</version> </dependency>
To use the SDK with a Gradle build process, use the following dependency.
configuration('com.kinde.spring:kinde-springboot-starter:+')
This library can be configured in different ways, via environment variables, via .env file and via the Spring Boot application.yaml file.
export KINDE_DOMAIN=https://<replace>.kinde.com # This is the domain you setup at kindeexport KINDE_CLIENT_ID=<replace> # the id for the client connecting to Kindeexport KINDE_CLIENT_SECRET=<replace> # the secret used to authenticate the client against Kindeexport KINDE_REDIRECT_URI=http://localhost:< replace with port of application server >/kinde-j2ee-app/loginexport KINDE_GRANT_TYPE=CODEexport KINDE_SCOPES=profile,email,openid
KINDE_DOMAIN=https://<replace>.kinde.com # This is the domain you setup at kindeKINDE_CLIENT_ID=<replace> # the id for the client connecting to KindeKINDE_CLIENT_SECRET=<replace> # the secret used to authenticate the client against KindeKINDE_REDIRECT_URI=http://localhost:< replace with port of application server >/kinde-j2ee-app/loginKINDE_GRANT_TYPE=CODEKINDE_SCOPES=profile,email,openid
application.yaml
kinde: oauth2: domain: https://< replace >.kinde.com client-id: < replace > client-secret: < replace > scopes: openid,email,profile
You can access Kinde’s API endpoints through the Kinde Management API. This lets developers work programmatically, rather than through the main Kinde interface.
The Kinde Management Library contains the components needed to access the Kinde Management API. It includes an OpenAPI-generated stub and a KindeAdminSession
tool that instantiates the ApiClient
using OIDC details.
To use this SDK, include the following dependency in your pom.xml
:
<dependency> <groupId>com.kinde</groupId> <artifactId>kinde-management</artifactId> <version>[2.0.1,)</version></dependency>
For Gradle, add the following dependency to your build file:
implementation('com.kinde:kinde-management:+')
Clone the repository to your machine:
git clone https://github.com/kinde-oss/kinde-java-sdk
Go into the project:
cd kinde-java-sdk
Install the dependencies:
mvn clean install
Maven automatically downloads the dependency from your local repository and makes it available in your project.
The following basic environment variables are required at a mimimum for connecting to the Kinde Management API.
export KINDE_DOMAIN=https://<replace>.kinde.com # This is the domain you setup at kindeexport KINDE_CLIENT_ID=<replace> # the id for the client connecting to Kindeexport KINDE_CLIENT_SECRET=<replace> # the secret used to authenticate the client against Kindeexport KINDE_SCOPES=openid # the scope as we are using an OpenID connectionexport KINDE_AUDIENCE=https://<replace>.kinde.com/api # the audience we need access to
The Kinde library supports .env files. The must be located in the directory from which the application is executed.
KINDE_DOMAIN=https://burntjam.kinde.comKINDE_CLIENT_ID=<replace>KINDE_CLIENT_SECRET=<replace>KINDE_SCOPES=openidKINDE_AUDIENCE=https://<replace>.kinde.com/api
If you want to pass in configuration programmatically, the KindeClientBuilder
supports the following approach.
KindeClient kindeClient = KindeClientBuilder .builder() .domain("<replace>") .clientId("<replace>") .clientSecret("<replace>") .addScope("<replace>") .addAudience("https://<replace>.kinde.com/api") .build();
ApiClient
This example gets an ApiClient
instance and then creates an ApplicationApi
instance using the ApiClient
.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeAdminSession kindeAdminSession = KindeAdminSessionBuilder.builder().client(kindeClient).build();ApiClient apiClient = kindeAdminSession.initClient();ApplicationsApi applicationsApi = new ApplicationsApi(apiClient);
Register your first user by signing up yourself. You’ll see your newly registered user on the Users page in Kinde.
The user permissions are available in two ways. One is from the ID token as a claim, the other is via the Kinde Management API.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeTokens tokens = kindeClient.getKindeClient().initClientSession(code,authorizationUrl).retrieveTokens();List<String> permissions = new ArrayList<String>();permissions.addAll(tokens.getAccessToken().getPermissions());
The permissions are up to you to define. The code below provides an example on how to retrieve the permissions from the portal using the Kinde Management API.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeAdminSession kindeAdminSession = KindeAdminSessionBuilder.builder().client(kindeClient).build();ApiClient apiClient = kindeAdminSession.initClient();OrganizationApi organizationApi = new OrganizationApi(apiClient);
// org code is the org that the user is associated with// user id is the user// expandedorganizationApi.getOrganizationUserPermissions(orgCode, userId, expand)
Use the OrganizationApi
to create a new organization.
KindeClient kindeClient = KindeClientBuilder .builder() .build();KindeAdminSession kindeAdminSession = KindeAdminSessionBuilder.builder().client(kindeClient).build();ApiClient apiClient = kindeAdminSession.initClient();OrganizationApi organizationApi = new OrganizationApi(apiClient);
// org code is the org that the user is associated with// user id is the user// expandedorganizationApi.createOrganization(new CreateOrganizationRequest().name("test"));
If you need help connecting to Kinde, please contact us at support@kinde.com.