
Implémentation de Delphi de JWT (Token Web JSON) et de spécification Jose (JSON Object Signing and Encryption). Cette bibliothèque prend en charge les sérialisations compactes JWS (support JWE est planifiée) avec plusieurs algorithmes Jose.

Avant Delphi 10 Seattle, l'algorithme HMAC-SHA utilise OpenSSL via la bibliothèque Indy, donc afin de générer le jeton, vous devez avoir les DLL OpenSSL dans votre système de serveur.
Dans les versions Delphi 10 Seattle ou plus récentes de Delphi, l'algorithme HMAC est également dans l'unité System.Hash, donc OpenSSL n'est pas nécessaire.
L'algorithme HMAC-RSA (ECDSA) utilise nécessairement OpenSSL, donc si vous prévoyez d'utiliser ces algorithmes pour signer votre jeton, vous devez télécharger et déployer OpenSSL (sur le serveur).
Veuillez garder à l'esprit que le client n'a pas à générer ou à vérifier le jeton (en utilisant SHA ou RSA), donc le côté client n'est pas nécessaire pour les DLL OpenSSL.
Si vous avez besoin de la bibliothèque OpenSSL sur le serveur, vous pouvez télécharger le package directement sur la page du projet GitHub d'Indy (gardez à l'esprit pour toujours mettre à jour la dernière version et pour correspondre à la bibliothèque de votre application)
Jose est une norme qui fournit une approche générale de la signature et du cryptage de tout contenu. Jose se compose de plusieurs RFC:
| Algorithmes | Soutenu |
|---|---|
exp | ✔️ |
iat | ✔️ |
nbf | ✔️ |
aud | ✔️ |
iss | ✔️ |
jti | ✔️ |
typ | ✔️ |
TJOSEProducer et TJOSEProducerBuilder (alias TJOSEProcess ) pour construire un nouveau jeton compact avec de nombreuses options TJOSEConsumer et TJOSEConsumerBuilder pour valider le jeton avec une granularité fine| Algorithmes | Soutenu |
|---|---|
None | ✔️ Ne l'utilisez pas! ? |
HS256 | ✔️ |
HS384 | ✔️ |
HS512 | ✔️ |
RS256 | ✔️ mis à jour! |
RS384 | ✔️ mis à jour! |
RS512 | ✔️ mis à jour! |
ES256 | ✔️ NOUVEAU! ? |
ES384 | ✔️ NOUVEAU! ? |
ES512 | ✔️ NOUVEAU! ? |
ES256K | ✔️ NOUVEAU! ? |
NoneCette bibliothèque a été testée avec Delphi 12 Athènes , Delphi 11 Alexandria , Delphi 10.4 Sydney , Delphi 10.3 Rio , Delphi 10.2 Tokyo mais avec un peu de travail, il devrait compiler avec DXE6 et plus, mais je n'ai pas essayé ou testé, si vous réussissez dans cette tâche, je serai heureux de créer une branche de votre travail!
Cette bibliothèque n'a aucune dépendance sur les bibliothèques / unités externes.
Unités de Delphi utilisées:
Ajoutez simplement le chemin source "Source / Common" et Source / Jose "à votre chemin de projet Delphi et .. vous êtes prêt à partir!
Utilisation de la commande boss install :
$ boss install github.com/paolo-rossi/delphi-jose-jwt Pour créer un jeton, créez simplement une instance de la classe TJWT et définissez les propriétés (affirmations).
La façon la plus simple de construire un jeton JWT (représentation compacte) est d'utiliser l'interface IJOSEProducer :
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 ; Une autre façon de sérialiser, de désérialiser, de vérifier un jeton consiste à utiliser la classe d'utilité TJOSE :
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 ; En utilisant les classes TJWT , TJWS et TJWK vous avez plus de contrôle sur la création du jeton compact final.
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 ;
Le déballage et la vérification des jetons sont simples.
Vous devez passer la clé et le format compact de jeton à la fonction TJOSE.Verify class
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 ; En utilisant la nouvelle classe TJOSEConsumer il est très facile de valider les affirmations du jeton. L'objet TJOSEConsumer est construit avec la classe d'utilité TJOSEConsumerBuilder à l'aide de l'interface fluide.
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 ;