Git Product home page Git Product logo

delphi-jose-jwt's Introduction

Delphi JOSE and JWT Library


Delphi JWT Library

What is Delphi JOSE and JWT Library

Top language GitHub license GitHub issues GitHub PR GitHub release GitHub commit activity GitHub last commit GitHub contributors

Delphi implementation of JWT (JSON Web Token) and the JOSE (JSON Object Signing and Encryption) specification suite. This library supports the JWS (JWE support is planned) compact serializations with several JOSE algorithms.

Image of Delphi-JOSE Demo

๐Ÿ“š Articles about using Delphi-JOSE

โš ๏ธ Important: OpenSSL requirements

HMAC using SHA algorithm

Prior to Delphi 10 Seattle the the HMAC-SHA algorithm uses OpenSSL through the Indy library, so in order to generate the token you should have the OpenSSL DLLs in your server system.

In Delphi 10 Seattle or newer Delphi versions the HMAC algorithm is also in the System.Hash unit so OpenSSL is not needed.

HMAC using RSA or ECDSA algorithm

The HMAC-RSA(ECDSA) algorithm uses necessarily OpenSSL so if you plan to use these algorithms to sign your token you have to download and deploy OpenSSL (on the server).

Client-side considerations

Please keep in mind that the client doesn't have to generate or verify the token (using SHA or RSA) so on the client-side there's no need for the OpenSSL DLLs.

OpenSSL download

If you need the OpenSSL library on the server, you can download the package directly to the Indy's GitHub project page (keep in mind to always update to the latest version and to match you application's bitness)

โ“ What is JOSE

JOSE is a standard that provides a general approach to the signing and encryption of any content. JOSE consists of several RFC:

โšก General Features

Token serialization

  • One method call to serialize a token

Token deserialization

  • One method call to validate and deserialize a compact token

Token & Claims validation (Consumer)

Algorithms Supported
exp โœ”๏ธ
iat โœ”๏ธ
nbf โœ”๏ธ
aud โœ”๏ธ
iss โœ”๏ธ
jti โœ”๏ธ
typ โœ”๏ธ

Easy to use classes for compact token productiom

  • Easy to use TJOSEProducer and TJOSEProducerBuilder (alias TJOSEProcess) classes to build a new compact token with many options

Easy to use classes for custom validation

  • Easy to use TJOSEConsumer and TJOSEConsumerBuilder classes to validate token with a fine granularity
  • Easy to write custom validators!

Signing algorithms

Algorithms Supported
None โœ”๏ธ don't use it! ๐Ÿ’€
HS256 โœ”๏ธ
HS384 โœ”๏ธ
HS512 โœ”๏ธ
RS256 โœ”๏ธ updated! ๐Ÿ”ฅ
RS384 โœ”๏ธ updated! ๐Ÿ”ฅ
RS512 โœ”๏ธ updated! ๐Ÿ”ฅ
ES256 โœ”๏ธ new! ๐ŸŒŸ
ES384 โœ”๏ธ new! ๐ŸŒŸ
ES512 โœ”๏ธ new! ๐ŸŒŸ
ES256K โœ”๏ธ new! ๐ŸŒŸ

Security notes

Projects using Delphi JOSE and JWT

๐Ÿ”ง Todo

Features
  • JWE support
  • Support of other crypto libraries (TMS Cryptography Pack, etc...)
Code
  • More unit tests
  • More examples

๐Ÿช Prerequisite

This library has been tested with Delphi 12 Athens, Delphi 11 Alexandria, Delphi 10.4 Sydney, Delphi 10.3 Rio, Delphi 10.2 Tokyo but with some work it should compile with DXE6 and higher but I have not tried or tested this, if you succeed in this task I will be happy to create a branch of your work!

Libraries/Units dependencies

This library has no dependencies on external libraries/units.

Delphi units used:

  • System.JSON (DXE6+) (available on earlier Delphi versions as Data.DBXJSON)
  • System.Rtti (D2010+)
  • System.Generics.Collections (D2009+)
  • System.NetEncoding (DXE7+)
  • Indy units: IdHMAC, IdHMACSHA1, IdSSLOpenSSL, IdHash

Indy notes

๐Ÿ’พ Installation

Manual installation

Simply add the source path "Source/Common" and Source/JOSE" to your Delphi project path and.. you are good to go!

Boss package manager

Using the boss install command:

$ boss install github.com/paolo-rossi/delphi-jose-jwt

๐Ÿ“œ Quick Code Examples

Creating a token

To create a token, simply create an instance of the TJWT class and set the properties (claims).

Using TJOSE utility class

The easiest way to build a JWT token (compact representation) is to use the IJOSEProducer interface:

uses
  JOSE.Producer;

var
  LResult: string;
begin
  LResult := TJOSEProcess.New
    .SetIssuer('Delphi JOSE Library')
    .SetIssuedAt(Now)
    .SetExpiration(Now + 1)
    .SetAlgorithm(LAlg)
    .SetKey(TJOSEAlgorithmId.HS256)
    .Build
    .GetCompactToken
  ;

  memoCompact.Lines.Add(LResult);
end;

Using TJOSE utility class

Another way to serialize, deserialize, verify a token is to use the TJOSEutility class:

uses
  JOSE.Core.JWT,
  JOSE.Core.Builder;

var
  LToken: TJWT;
  LCompactToken: string;
begin
  LToken := TJWT.Create;
  try
    // Token claims
    LToken.Claims.Issuer := 'WiRL REST Library';
    LToken.Claims.Subject := 'Paolo Rossi';
    LToken.Claims.Expiration := Now + 1;

    // Signing and Compact format creation
    LCompactToken := TJOSE.SHA256CompactToken('my_very_long_and_safe_secret_key', LToken);
    mmoCompact.Lines.Add(LCompactToken);
  finally
    LToken.Free;
  end;

Using TJWT, TJWS and TJWK classes

Using the TJWT, TJWS and TJWK classes you have more control over the creation of the final compact token.

var
  LToken: TJWT;
  LSigner: TJWS;
  LKey: TJWK;
  LAlg: TJOSEAlgorithmId;
begin
  LToken := TJWT.Create;
  try
    // Set your claims
    LToken.Claims.Subject := 'Paolo Rossi';
    LToken.Claims.Issuer := 'Delphi JOSE Library';
    LToken.Claims.IssuedAt := Now;
    LToken.Claims.Expiration := Now + 1;

    // Choose the signing algorithm
    case cbbAlgorithm.ItemIndex of
      0: LAlg := TJOSEAlgorithmId.HS256;
      1: LAlg := TJOSEAlgorithmId.HS384;
      2: LAlg := TJOSEAlgorithmId.HS512;
    else LAlg := TJOSEAlgorithmId.HS256;
    end;

    // Create your key from any text or TBytes
    LKey := TJWK.Create(edtSecret.Text);

    try
      // Create the signer
      LSigner := TJWS.Create(LToken);
      try
        // With this option you can have keys < algorithm length
        LSigner.SkipKeyValidation := True;

        // Sign the token!
        LSigner.Sign(LKey, LAlg);

        memoCompact.Lines.Add('Header: ' + LSigner.Header);
        memoCompact.Lines.Add('Payload: ' + LSigner.Payload);
        memoCompact.Lines.Add('Signature: ' + LSigner.Signature);
        memoCompact.Lines.Add('Compact Token: ' + LSigner.CompactToken);
      finally
        LSigner.Free;
      end;
    finally
      LKey.Free;
    end;  
  finally
    LToken.Free;
  end;

Unpack and verify a token's signature

Unpacking and verifying tokens is simple.

Using TJOSE utility class

You have to pass the key and the token compact format to the TJOSE.Verify class function

var
  LKey: TJWK;
  LToken: TJWT;
begin
  // Create the key from a text or TBytes
  LKey := TJWK.Create('my_very_long_and_safe_secret_key');

  // Unpack and verify the token!
  LToken := TJOSE.Verify(LKey, FCompactToken);

  if Assigned(LToken) then
  begin
    try
      if LToken.Verified then
        mmoJSON.Lines.Add('Token signature is verified')
      else
        mmoJSON.Lines.Add('Token signature is not verified')
    finally
      LToken.Free;
    end;
  end;

end;

Unpacking and token validation

Using the new class TJOSEConsumer it's very easy to validate the token's claims. The TJOSEConsumer object is built with the TJOSEConsumerBuilder utility class using the fluent interface.

var
  LConsumer: IJOSEConsumer;
begin
  LConsumer := TJOSEConsumerBuilder.NewConsumer
    .SetClaimsClass(TJWTClaims)

    // JWS-related validation
    .SetVerificationKey(edtConsumerSecret.Text)
    .SetSkipVerificationKeyValidation
    .SetDisableRequireSignature

    // string-based claims validation
    .SetExpectedSubject('paolo-rossi')
    .SetExpectedAudience(True, ['Paolo'])

    // Time-related claims validation
    .SetRequireIssuedAt
    .SetRequireExpirationTime
    .SetEvaluationTime(IncSecond(FNow, 26))
    .SetAllowedClockSkew(20, TJOSETimeUnit.Seconds)
    .SetMaxFutureValidity(20, TJOSETimeUnit.Minutes)

    // Build the consumer object
    .Build();

  try
    // Process the token with your rules!
    LConsumer.Process(Compact);
  except
    // (optionally) log the errors
    on E: Exception do
      memoLog.Lines.Add(E.Message);
  end;

Paolo Rossi

delphi-jose-jwt's People

Contributors

paolo-rossi avatar wlandgraf avatar ccy avatar fabioxgn avatar stefanon-infotronics avatar viniciussanchez avatar adrianosantostreina avatar bernd5 avatar dbcto avatar fulgan avatar hunsche avatar markrsill avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.