The Kinde Elixir SDK allows developers to use this library for the Kinde Business.
If you haven’t already got a Kinde account, register for free here (no credit card required).
You need a Kinde domain to get started, e.g. yourapp.kinde.com
.
Add the following dependency in your project:
{:kinde_sdk, path: "/path/to/kinde-elixir-sdk"}
and add to your extra applications:
def application do
[
extra_applications: [:logger, :kinde_sdk]
]
end
You need to follow these steps to setup the project properly:
- Create .env file at the root
- Add the following lines in there:
export KINDE_BACKEND_CLIENT_ID="6c43a124bc114dc0bf78889ae89349b3"
export KINDE_FRONTEND_CLIENT_ID="2e41e9e798004177b1b44aa1e1ad3d62"
export KINDE_CLIENT_SECRET="Tz9oKlQGW1VJX2FUoLdaeUHjCMnlNccHTW1fyOWlO4krBb4P1G"
export KINDE_REDIRECT_URL="http://localhost:4000/callback"
export KINDE_DOMAIN="https://elixirsdk2.kinde.com"
export KINDE_LOGOUT_REDIRECT_URL="http://localhost:4000/logout"
export KINDE_PKCE_LOGOUT_URL="http://localhost:4000/logout"
export KINDE_PKCE_REDIRECT_URL="http://localhost:4000/pkce-callback"
export KINDE_BASE_URL="https://app.kinde.com"
- Don't forget to update the values of above keys with your kinde-account keys to make the app up and running.
- Optionally, you can also set
scope
as well.
config :kinde_sdk, scope: "email"
- Once you're done with above steps, open the console and write
source .env
before any mix command. - Note: This configuration is very important, you won't be able to compile the project, as well as no tests will run successfully until you follow these steps.
You need to follow these steps to setup the existing project properly:
- Create .env file at the root
- Add the following lines in there:
export KINDE_BACKEND_CLIENT_ID="6c43a124bc114dc0bf78889ae89349b3"
export KINDE_FRONTEND_CLIENT_ID="2e41e9e798004177b1b44aa1e1ad3d62"
export KINDE_CLIENT_SECRET="Tz9oKlQGW1VJX2FUoLdaeUHjCMnlNccHTW1fyOWlO4krBb4P1G"
export KINDE_REDIRECT_URL="http://localhost:4000/callback"
export KINDE_DOMAIN="https://elixirsdk2.kinde.com"
export KINDE_LOGOUT_REDIRECT_URL="http://localhost:4000/logout"
export KINDE_PKCE_LOGOUT_URL="http://localhost:4000/logout"
export KINDE_PKCE_REDIRECT_URL="http://localhost:4000/pkce-callback"
export KINDE_BASE_URL="https://app.kinde.com"
- Don't forget to replace the values to your own application-keys, these are just dummy keys (might not work)
- Also make sure that your project has runtime.exs file in the config directory which has following piece of code written in it:
import Config
import Envar
Envar.load(".env")
# configure kinde_sdk on runtime
config :kinde_sdk,
backend_client_id: Envar.get("KINDE_BACKEND_CLIENT_ID"),
frontend_client_id: Envar.get("KINDE_FRONTEND_CLIENT_ID"),
client_secret: Envar.get("KINDE_CLIENT_SECRET"),
redirect_url: Envar.get("KINDE_REDIRECT_URL"),
domain: Envar.get("KINDE_DOMAIN"),
logout_redirect_url: Envar.get("KINDE_LOGOUT_REDIRECT_URL"),
pkce_logout_url: Envar.get("KINDE_PKCE_LOGOUT_URL"),
pkce_callback_url: Envar.get("KINDE_PKCE_REDIRECT_URL")
Initialize your client like this:
{conn, client} =
KindeClientSDK.init(
conn,
Application.get_env(:kinde_sdk, :domain),
Application.get_env(:kinde_sdk, :redirect_url),
Application.get_env(:kinde_sdk, :backend_client_id),
Application.get_env(:kinde_sdk, :client_secret),
:client_credentials,
Application.get_env(:kinde_sdk, :logout_redirect_url)
)
KindeClientSDK implements three OAuth flows: Client Credentials flow, Authorisation Code flow and Authorisation Code with PKCE flow. Each flow can be used with their corresponding grant type when initializing a client.
OAuth Flow | Grant Type | Type |
---|---|---|
Client Credentials | :client_credentials | atom |
Authorisation Code | :authorization_code | atom |
Authorisation Code with PKCE | :authorization_code_flow_pkce | atom |
KindeClientSDK implements persistant ETS cache for storing the client data and authenticating variables.
You may call your created client like this:
client = KindeClientSDK.get_kinde_client(conn)
conn = KindeClientSDK.login(conn, client)
conn = KindeClientSDK.register(conn, client)
When the user is redirected back to your site from Kinde, this will call your callback URL defined in the redirect_url
config. You will need to route /callback
to call a function to handle this.
def callback(conn, _params) do
{conn, client} = KindeClientSDK.get_token(conn)
data = KindeClientSDK.get_all_data(conn)
IO.inspect(data.access_token, label: "kinde_access_token") # Tip: This line is not mandatory, as its just console-printing
end
We can use Kinde helper function to get the tokens generated by login
and get_token
functions.
data = KindeClientSDK.get_all_data(conn)
IO.inspect(data.login_time_stamp, label: "Login Time Stamp") # Tip: This line is not mandatory, as its just console-printing
Or first calling the get_token
function:
{conn, client} = KindeClientSDK.get_token(conn)
You need to have already authenticated before you call the API, otherwise an error will occur.
KindeClientSDK.get_user_detail(conn)
To have a new organization created within your application
conn = KindeClientSDK.create_org(conn, client)
conn = KindeClientSDK.create_org(conn, client)
The Kinde SDK client comes with a logout method.
conn = KindeClientSDK.logout(conn)
Returns whether if a user is logged in.
KindeClientSDK.authenticated?(conn)
We have provided a helper to grab any claim from your id or access tokens. The helper defaults to access tokens:
KindeClientSDK.get_claims(conn)
KindeClientSDK.get_claim(conn, "jti", :id_token)
We provide helper functions to more easily access permissions:
KindeClientSDK.get_permissions(conn)
KindeClientSDK.get_permission(conn, "create:users")
An audience
is the intended recipient of an access token - for example the API for your application. The audience argument can be passed to the Kinde client to request an audience be added to the provided token.
additional_params = %{
audience: "api.yourapp.com"
}
KindeClientSDK.init(
conn,
Application.get_env(:kinde_sdk, :domain),
Application.get_env(:kinde_sdk, :redirect_url),
Application.get_env(:kinde_sdk, :backend_client_id),
Application.get_env(:kinde_sdk, :client_secret),
:authorization_code_flow_pkce,
Application.get_env(:kinde_sdk, :logout_redirect_url),
"openid profile email offline",
additional_params
)
For details on how to connect, see Register an API
By default the KindeSDK requests the following scopes:
- profile
- offline
- openid
You can override this by passing scope into the KindeSDK.
Property | Type | Is required | Default | Description |
---|---|---|---|---|
domain | string | Yes | Either your Kinde instance url or your custom domain. e.g: https://yourapp.kinde.com | |
redirect_url | string | Yes | The url that the user will be returned to after authentication | |
backend_client_id | string | Yes | The id of your backend application | |
frontend_client_id | string | Yes | The id of your frontend application | |
client_secret | string | Yes | The id secret of your application - get this from the Kinde admin area | |
logout_redirect_url | string | Yes | Where your user will be redirected upon logout | |
scope | string | No | openid profile email offline | The scopes to be requested from Kinde |
additional_parameters | map | No | %{} | Additional parameters that will be passed in the authorization request |
additional_parameters - audience | string | No | The audience claim for the JWT | |
additional_parameters - org_name | string | No | The org claim for the JWT | |
additional_parameters - org_code | string | No | The org claim for the JWT |
Function | Description | Arguments | Usage |
---|---|---|---|
login | Constructs redirect url and sends user to Kinde to sign in | conn, client | KindeClientSDK.login(conn, client) |
register | Constructs redirect url and sends user to Kinde to sign up | conn, client | KindeClientSDK.register(conn, client) |
logout | Logs the user out of Kinde | conn | KindeClientSDK.logout(conn) |
get_token | Returns the raw access token from URL after logged from Kinde | conn | KindeClientSDK.get_token(conn) |
create_org | Constructs redirect url and sends user to Kinde to sign up and create a new org for your business | conn, client | KindeClientSDK.create_org(conn, client) |
get_claims | Gets all claims from an access or id token | conn, atom | KindeClientSDK.get_claims(conn) or KindeClientSDK.get_claims(conn, :id_token) |
get_claim | Gets a claim-object from an access or id token | conn, string, atom | KindeClientSDK.get_claim(conn, "jti") or KindeClientSDK.get_claim(conn, "jti", :id_token) |
get_permissions | Returns the state of a all permissions | conn, atom | KindeClientSDK.get_permissions(conn, :id_token) |
get_permission | Returns the state of a given permission | conn, string | KindeClientSDK.get_permission(conn, "create:users") |
get_organization | Get details for the organization your user is logged into | conn | KindeClientSDK.get_user_organization(conn) |
get_user_detail | Returns the profile for the current user | conn | KindeClientSDK.get_user_detail(conn) |
get_user_organizations | Returns the org code from the user token | conn | KindeClientSDK.get_user_organizations(conn) |
get_cache_pid | Returns the Kinde cache PID from the conn |
conn | KindeClientSDK.get_cache_pid(conn) |
save_kinde_client | Saves the Kinde client created into the conn |
conn | KindeClientSDK.save_kinde_client(conn) |
get_kinde_client | Returns the Kinde client created from the conn |
conn | KindeClientSDK.get_kinde_client(conn) |
get_all_data | Returns all the Kinde data (tokens) returned | conn | KindeClientSDK.get_all_data(conn) |
Function | Description | Arguments | Usage |
---|---|---|---|
get_flag/2 | Detail of any certain feature-flag | conn, code | KindeClientSDK.get_flag(conn, code) |
get_flag/3 | Detail of any certain feature-flag | conn, code, default_value | KindeClientSDK.get_flag(conn, code, default_value) |
get_flag/4 | Detail of any certain feature-flag | conn, code, default_value, flag_type | KindeClientSDK.get_flag(conn, code, default_value, flag_type) |
get_boolean_flag/2 | Returns the boolean-flag from conn | conn, code | KindeClientSDK.get_boolean_flag(conn, code) |
get_boolean_flag/3 | Returns the boolean-flag from conn | conn, code, default_value | KindeClientSDK.get_boolean_flag(conn, code, default_value) |
get_string_flag/2 | Returns the string-flag from conn | conn, code | KindeClientSDK.get_string_flag(conn, code) |
get_string_flag/3 | Returns the string-flag from conn | conn, code, default_value | KindeClientSDK.get_string_flag(conn, code, default_value) |
get_integer_flag/2 | Returns the integer-flag from conn | conn, code | KindeClientSDK.get_integer_flag(conn, code) |
get_integer_flag/3 | Returns the integer-flag from conn | conn, code, default_value | KindeClientSDK.get_integer_flag(conn, code, default_value) |