Kinde.SDK 1.1.0

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package Kinde.SDK --version 1.1.0                
NuGet\Install-Package Kinde.SDK -Version 1.1.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Kinde.SDK" Version="1.1.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Kinde.SDK --version 1.1.0                
#r "nuget: Kinde.SDK, 1.1.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Kinde.SDK as a Cake Addin
#addin nuget:?package=Kinde.SDK&version=1.1.0

// Install Kinde.SDK as a Cake Tool
#tool nuget:?package=Kinde.SDK&version=1.1.0                

Kinde SDK

Setup and configuration

Identity provider configuration contains these parameters:

  • Domain. Base domain used for authorization. must be subdomain of kinde.com. F.E. testauth.kinde.com
  • ReplyUrl. Unused for client credentials, but used as callback url for other flows. May be null for client credentials
  • LogoutUrl. Url for redirection after logout.

Additional requirements (based on flow)

  • ClientID, required.
  • ClientSecret, required.
  • Scope, required.
  • State, optional. Can be set to null, then will be autogenerated. <b> Note, that state parameter must not be constant. It must be random for each call.</b>
  • Code verifier generic parameter, required. Use inbuilt SHA256CodeVerifier, or create other one if needed.

SDK supports configuration from appsetings.json. Also, you can write your own implementation of IAuthorizationConfigurationProvider and IIdentityProviderConfigurationProvider. Configuration example:

"ApplicationConfiguration": {
    "Domain": "https://testauth.kinde.com",
    "ReplyUrl": "https://localhost:7165/home/callback",
    "LogoutUrl":  "https://localhost:7165/home"
  },
  "DefaultAuthorizationConfiguration": {
    "ConfigurationType": "Kinde.Api.Models.Configuration.PKCES256Configutation",
    "Configuration": {
      "State": null,
      "ClientId": "reg@live",
      "Scope": "openid offline",
      "GrantType": "code id_token token",
      "ClientSecret": "<my secret>"
    }
  },

Also, you should register configuration providers using .net DI:

builder.Services.AddTransient<IAuthorizationConfigurationProvider, DefaultAuthorizationConfigurationProvider>();
builder.Services.AddTransient<IApplicationConfigurationProvider, DefaultApplicationConfigurationProvider>();

PKCES256Configutation is most complicated configuration and contains all necessary properties. Configuration for Authentication code is same and for Client credentials State is not applicable. But it is not mandatory to remove it. All availiable types are:

  1. Kinde.Api.Models.Configuration.PKCES256Configutation
  2. Kinde.Api.Models.Configuration.AuthorizationCodeConfiguration
  3. Kinde.Api.Models.Configuration.ClientCredentialsConfiguration

Besides configuration, all code approach is quite similar. Only difference is if authorization flow requires user redirection or not. For Client configuration Authorize() call is enough for authoriztion. For others (PKCE and Authorization code) you should handle redirection to Kinde (as IdP) and handle callback to end authorization.

1. Login with no redirection, using Client credentials flow
Don't use autogenerated constructor without <code>IIdentityProviderConfiguration</code> parameter. This will throw exceptions.

For not web application only client credentials flow can be used. Because other flows requires user interaction via browser. Example: <br>

var client = new Kinde.KindeClient(
    new IdentityProviderConfiguration("https://testauth.kinde.com", "https://test.domain.com/callback", "https://test.domain.com/logout"), 
    new KindeHttpClient());
await client.Authorize(new ClientCredentialsConfiguration("clientId_here","openid offline any_other_scope", "client secret here"));
// Api call
//   vvv
var myOrganization  = client.CreateOrganizationAsync("My new best organization");

After this you can call any api methods on this instance.

2. Login with redirection, using PKCE256 flow or Authorization code
Don't use autogenerated constructor without <code>IIdentityProviderConfiguration</code> parameter. This will throw exceptions.

For web applications api clients should be connected to user session. To keep them sync use <code>KindeClientFactory</code>. I t has thread safe dictionary to save client instances. It is highly recommended to use Session Id or something like this as a key for instance.

Example:<br>

   public async Task<IActionResult> Login()
   {
        // We need some artificial id to correlate user session to client instance
        //NOTE: Session.Id will be always random, we need to add something to session to make it persistent. 
        string correlationId = HttpContext.Session?.GetString("KindeCorrelationId");
        if (string.IsNullOrEmpty(correlationId))
        {
            correlationId = Guid.NewGuid().ToString();
            HttpContext.Session.SetString("KindeCorrelationId", correlationId);
        }
        // Get client's instance...
        var client = KindeClientFactory.Instance.GetOrCreate(correlationId, _appConfigurationProvider.Get());
        // ...and authorize it
        await client.Authorize(_authConfigurationProvider.Get());
        // if auth flow is not ClientCredentials flow, we need to redirect user to another page
        if (client.AuthotizationState == Api.Enums.AuthorizationStates.UserActionsNeeded)
        {
            // redirect user to login page
            return Redirect(await client.GetRedirectionUrl(correlationId));
        }
        return RedirectToAction("Index");
   }

This code won't authenticate user complletely. We should wait for data on callback endpoint and execute this: <br>

        public IActionResult Callback(string code, string state)
        {
            Kinde.KindeClient.OnCodeRecieved(code, state);
            string correlationId = HttpContext.Session?.GetString("KindeCorrelationId");
            var client = KindeClientFactory.Instance.Get(correlationId); //already authorized instance
            // Api call
            //   vvv
            var myOrganization  = client.GetUserAsync();
            return RedirectToAction("Index");
        }

Register user

User registration is same as authorization. With one tiny difference:

     public async Task<IActionResult> SignUp()
        {
            string correlationId = HttpContext.Session?.GetString("KindeCorrelationId");
            if (string.IsNullOrEmpty(correlationId))
            {
                correlationId = Guid.NewGuid().ToString();
                HttpContext.Session.SetString("KindeCorrelationId", correlationId);
            }
            var client = KindeClientFactory.Instance.GetOrCreate(correlationId, _appConfigurationProvider.Get());
            await client.Register(_authConfigurationProvider.Get()); //<--- Pass true to register user
            if (client.AuthotizationState == Api.Enums.AuthorizationStates.UserActionsNeeded)
            {
                return Redirect(await client.GetRedirectionUrl(correlationId));
            }
            return RedirectToAction("Index");
        }
Logout

Logout has two steps: local cache cleanup and token revocation on Kinde side. So, client.Logout() method sholud be called. This method returns redirect url for token revocation. User should be redirected to it.

Logout example:

  public async Task<IActionResult> Logout()
        {
            string correlationId = HttpContext.Session?.GetString("KindeCorrelationId");
          
            var client = KindeClientFactory.Instance.GetOrCreate(correlationId, _appConfigurationProvider.Get());
             var url = await client.Logout();
            
            return Redirect(url);
        }
Token renewal

Token will renew automatically in background. If you want to do it manually, call Renew method. Example:

public async Task<IActionResult> Renew()
        {
            string correlationId = HttpContext.Session?.GetString("KindeCorrelationId");

            var client = KindeClientFactory.Instance.GetOrCreate(correlationId, _appConfigurationProvider.Get());
            await client.Renew();

            return RedirectToAction("Index");
        }

More usage examples can be found in Kinde.DemoMvc project.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.2.9 255 11/6/2024
1.2.8 99 10/31/2024
1.2.7 1,589 8/19/2024
1.2.6 16,082 4/10/2024
1.2.5 5,253 12/8/2023
1.2.4 127 12/7/2023
1.2.3 728 10/23/2023
1.2.2 133 10/17/2023
1.2.0 5,152 6/28/2023
1.1.0 193 4/14/2023
0.0.1 247 11/15/2022