Esta é uma documentação completa para a biblioteca jose em Dart. A biblioteca implementa os padrões de Javascript Object Signing and Encryption (JOSE), fornecendo funcionalidades para JWS, JWE, JWK, JWT e JWA.
- Visão Geral da Biblioteca
- Core (jose.dart)
- JSON Web Algorithms (jwa.dart)
- JSON Web Encryption (jwe.dart)
- JSON Web Key (jwk.dart)
- JSON Web Signature (jws.dart)
- JSON Web Token (jwt.dart)
- Utilitários (util.dart)
A biblioteca jose é uma implementação dos padrões JOSE definidos em várias RFCs da IETF. Ela permite a criação, manipulação, assinatura e criptografia de dados usando estruturas JSON.
Os principais componentes exportados são:
jose.dart: Classes centrais e estruturas base.jwk.dart: Manipulação de chaves criptográficas (JSON Web Key).jws.dart: Assinaturas digitais (JSON Web Signature).jwe.dart: Criptografia de conteúdo (JSON Web Encryption).jwt.dart: Tokens de acesso (JSON Web Token).jwa.dart: Definições de algoritmos (JSON Web Algorithm).
Este módulo contém as classes e estruturas fundamentais que formam a base para JWS e JWE.
Representa os parâmetros de cabeçalho JOSE, que são comuns a JsonWebSignature e JsonWebEncryption.
JoseHeader.fromJson(Map<String, dynamic> json): Constrói umJoseHeadera partir de um mapa JSON.JoseHeader.fromBase64EncodedString(String encodedString): Constrói umJoseHeadera partir de sua representação JSON codificada em base64url.
algorithm(String?): Identifica o algoritmo criptográfico (alg).jwkSetUrl(Uri?): URL para um conjunto de chaves públicas JWK (jku).jsonWebKey(JsonWebKey?): A chave pública JWK embutida (jwk).keyId(String?): Um hint para identificar a chave usada (kid).type(String?): O tipo de mídia do objeto JOSE completo (typ), como "JWT".contentType(String?): O tipo de mídia do payload (cty).critical(List<String>?): Indica extensões que devem ser entendidas e processadas (crit).encryptionAlgorithm(String?): O algoritmo de criptografia de conteúdo (usado apenas em JWE) (enc).compressionAlgorithm(String?): O algoritmo de compressão (usado apenas em JWE) (zip).
Classe base para JsonWebSignature e JsonWebEncryption.
data(List<int>): Os dados binários contidos no objeto (payload para JWS, ciphertext para JWE).recipients(List<JoseRecipient>): O conteúdo por destinatário (assinaturas para JWS, chaves criptografadas para JWE).commonHeader(JoseHeader): Um cabeçalho unificado contendo os parâmetros compartilhados e comuns entre os destinatários.commonProtectedHeader(JoseHeader): Um cabeçalho contendo apenas os parâmetros protegidos que são comuns.
JoseObject.fromJson(Map<String, dynamic> json): Constrói umJWSouJWEa partir de sua representação JSON.JoseObject.fromCompactSerialization(String serialization): Constrói umJWSouJWEa partir de sua representação compacta.
toCompactSerialization(): Serializa o objeto para o formato de string compacta. Lança uma exceção se houver múltiplos destinatários/assinaturas.toJson(): Serializa o objeto para sua representação JSON.verify(JsonWebKeyStore keyStore): Verifica se a assinatura/criptografia do objeto é válida usando as chaves dokeyStore. RetornaFuture<bool>.getPayload(JsonWebKeyStore keyStore, {List<String>? allowedAlgorithms}): Tenta descriptografar/verificar o objeto usando as chaves dokeyStoree retorna o payload (JosePayload). Lança umaJoseExceptionem caso de falha.
Representa o conteúdo específico para cada destinatário de um JoseObject.
protectedHeader(JsonObject?): Parâmetros de cabeçalho por destinatário que são protegidos por integridade.unprotectedHeader(JsonObject?): Parâmetros de cabeçalho por destinatário que não são protegidos.header(JoseHeader): Cabeçalho combinado (protegido e não protegido).data(List<int>): Os dados binários (assinatura para JWS, chave de conteúdo criptografada para JWE).
Representa o payload de um JWS ou JWE após a verificação/descriptografia.
data(List<int>): Os dados binários do payload.protectedHeader(JsonObject?): Os parâmetros de cabeçalho que foram protegidos.stringContent(String): O conteúdo do payload como uma string UTF-8.jsonContent(dynamic): O conteúdo do payload decodificado como JSON.mediaType(String?): O tipo de mídia do payload (parâmetroctydo cabeçalho).
Classe base para os builders JsonWebSignatureBuilder e JsonWebEncryptionBuilder.
content(setter): Define o payload (pode serString,List<int>ou um objeto JSON).setProtectedHeader(String key, dynamic value): Define um parâmetro de cabeçalho protegido compartilhado.addRecipient(JsonWebKey? key, {String? algorithm}): Adiciona um destinatário (com sua chave e algoritmo) para assinar ou criptografar o objeto.build(): Constrói o objetoJoseObjectfinal.
Uma exceção personalizada lançada pela biblioteca para indicar erros relacionados a operações JOSE.
Este módulo define os algoritmos criptográficos suportados, conforme especificado na RFC 7518.
Representa um algoritmo criptográfico JWA.
name(String): O nome do algoritmo (ex:HS256,RS256).type(String): A família do algoritmo (ex:oct,RSA,EC).use(String): O uso pretendido do algoritmo (sigpara assinatura,encpara criptografia,keypara gerenciamento de chaves).
A classe define constantes para todos os algoritmos suportados, como:
hs256,hs384,hs512(HMAC com SHA)rs256,rs384,rs512(RSASSA-PKCS1-v1_5 com SHA)es256,es384,es512,es256k(ECDSA)rsa1_5,rsa_oaep,rsa_oaep_256(Criptografia com RSA)a128kw,a192kw,a256kw(AES Key Wrap)a128cbc_hs256,a192cbc_hs384,a256cbc_hs512(AES-CBC com HMAC-SHA)a128gcm,a192gcm,a256gcm(AES-GCM)
getByName(String? name): Retorna uma instância deJsonWebAlgorithmpelo seu nome.find({String? operation, String? keyType}): Encontra algoritmos que correspondem a uma operação ou tipo de chave.
generateRandomKey({int? keyBitLength}): Gera umaJsonWebKeyaleatória adequada para este algoritmo.
Este módulo implementa a especificação JSON Web Encryption (JWE) para criptografar conteúdo.
Representa um objeto JWE com conteúdo criptografado.
JsonWebEncryption.fromCompactSerialization(String serialization): Constrói um JWE a partir de sua representação compacta.JsonWebEncryption.fromJson(Map<String, dynamic> json): Constrói um JWE a partir de sua representação JSON (geral ou achatada).
initializationVector(List<int>): O Vetor de Inicialização (IV) usado na criptografia.authenticationTag(List<int>): A tag de autenticação gerada pela criptografia autenticada.additionalAuthenticatedData(List<int>?): Dados adicionais que são protegidos por integridade, mas não criptografados.
Builder para criar objetos JsonWebEncryption.
encryptionAlgorithm(String?): O algoritmo de criptografia de conteúdo a ser usado (ex:A128CBC-HS256).additionalAuthenticatedData(List<int>?): Define os dados adicionais autenticados.
build(): Constrói o objetoJsonWebEncryption. Exige que um payload, um algoritmo de criptografia e pelo menos um destinatário tenham sido definidos.
Este módulo implementa a especificação JSON Web Key (JWK) para representar chaves criptográficas.
Representa uma chave criptográfica no formato JWK.
JsonWebKey.fromJson(Map<String, dynamic> json): A partir de um mapa JSON.JsonWebKey.fromCryptoKeys({PublicKey?, PrivateKey?}): A partir de chaves da bibliotecacrypto_keys.JsonWebKey.rsa(...),JsonWebKey.ec(...),JsonWebKey.symmetric(...): Construtores de conveniência para tipos de chave específicos.JsonWebKey.fromPem(String pem): Analisa uma chave em formato PEM.JsonWebKey.generate(String? algorithm): Gera uma nova chave aleatória para um algoritmo específico.
keyType(String): O tipo de chave (kty), comoRSA,EC,oct.keyId(String?): O identificador da chave (kid).algorithm(String?): O algoritmo pretendido para uso com a chave (alg).publicKeyUse(String?): O uso pretendido da chave pública (use), comosigouenc.keyOperations(Set<String>?): As operações permitidas para a chave (key_ops), comosign,verify,encrypt,decrypt.
sign(List<int> data, {String? algorithm}): Cria uma assinatura digital dos dados.verify(List<int> data, List<int> signature, {String? algorithm}): Verifica uma assinatura digital.encrypt(...): Criptografa dados.decrypt(...): Descriptografa dados.wrapKey(JsonWebKey key, ...): Criptografa outra chave (key wrapping).unwrapKey(List<int> data, ...): Descriptografa uma chave (key unwrapping).
Representa um conjunto de JsonWebKeys.
keys(List<JsonWebKey>): A lista de chaves no conjunto.
Um armazenamento para procurar e encontrar JsonWebKeys.
addKey(JsonWebKey key): Adiciona uma chave individual.addKeySet(JsonWebKeySet keys): Adiciona um conjunto de chaves.addKeySetUrl(Uri url): Adiciona uma URL de onde um conjunto de chaves pode ser baixado.findJsonWebKeys(JoseHeader header, String operation): Encontra chaves aplicáveis para uma determinada operação e cabeçalho JOSE.
Classe abstrata para carregar JsonWebKeySet de uma URL. A implementação padrão (DefaultJsonWebKeySetLoader) lida com esquemas http(s) e data, com cache para requisições HTTP.
Este módulo implementa a especificação JSON Web Signature (JWS) para assinar conteúdo.
Representa um objeto JWS com conteúdo assinado.
JsonWebSignature.fromCompactSerialization(String serialization): Constrói um JWS a partir de sua representação compacta.JsonWebSignature.fromJson(Map<String, dynamic> json): Constrói um JWS a partir de sua representação JSON (geral ou achatada).
unverifiedPayload(JosePayload): Retorna o payload sem verificar a assinatura. Use com cuidado!
Builder para criar objetos JsonWebSignature.
build(): Constrói o objetoJsonWebSignature. Exige que um payload e pelo menos um destinatário (para assinatura) tenham sido definidos.
Este módulo implementa a especificação JSON Web Token (JWT), que é comumente serializado como um JWS.
Representa o conjunto de claims (reivindicações) de um JWT.
issuer(Uri?): O emissor do token (iss).subject(String?): O "assunto" do token (sub).audience(List<String>?): Os destinatários pretendidos do token (aud).expiry(DateTime?): A data de expiração do token (exp).notBefore(DateTime?): A data antes da qual o token não deve ser aceito (nbf).issuedAt(DateTime?): A data em que o token foi emitido (iat).jwtId(String?): Um identificador único para o token (jti).
validate(...): Valida as claims contra critérios como tempo de expiração, emissor e audiência. Retorna uma lista de exceções se a validação falhar.
Representa um JWT.
JsonWebToken.unverified(String serialization): Decodifica um JWT de uma string JWS compacta, sem verificar a assinatura.JsonWebToken.decodeAndVerify(String serialization, JsonWebKeyStore keyStore, ...): O método principal e seguro para decodificar e verificar/descriptografar um JWT.
claims(JsonWebTokenClaims): As claims contidas no token.toCompactSerialization(): Serializa o JWT de volta para sua forma compacta.isVerified(bool?): Retornatruese o token foi verificado com sucesso,falsese a verificação falhou, ounullse não foi tentada.verify(JsonWebKeyStore keyStore, ...): Tenta verificar a assinatura do JWT.
Contém classes e funções auxiliares usadas em toda a biblioteca.
Uma classe base para objetos JSON imutáveis, com funcionalidades de (de)serialização e acesso a propriedades tipadas.
decodeBase64EncodedBytes(String encodedString): Decodifica uma string base64url para bytes.encodeBase64EncodedBytes(List<int> data): Codifica bytes para uma string base64url.encodeBigInt(BigInt? v): Codifica umBigIntpara base64url, como exigido pelo padrão JWK.safeUnion(...)ecommonUnion(...): Funções para mesclar mapas de cabeçalho.
A biblioteca jose para Dart é uma implementação robusta das especificações IETF JavaScript Object Signing and Encryption (JOSE).
Ela fornece as ferramentas necessárias para trabalhar com os padrões de segurança mais comuns – fundamentais em sistemas de autenticação e autorização modernos como OpenID Connect e OAuth 2.0.
- JWS – JSON Web Signature (RFC 7515): cria e verifica assinaturas digitais em payloads, garantindo integridade e autenticidade.
- JWE – JSON Web Encryption (RFC 7516): criptografa conteúdos, garantindo confidencialidade.
- JWK – JSON Web Key (RFC 7517): representa chaves criptográficas em JSON, facilitando distribuição e uso de chaves públicas.
- JWA – JSON Web Algorithm (RFC 7518): define os algoritmos criptográficos utilizados em JWS e JWE.
- JWT – JSON Web Token (RFC 7519): padrão para criar tokens que carregam claims; muito usado para transmitir identidade entre provedor de identidade e aplicação.
Adicione a dependência no arquivo pubspec.yaml:
dependencies:
jose: ^0.3.3 # Use a versão mais recente disponível em pub.devDepois execute:
dart pub get # ou
flutter pub get| Classe | Descrição |
|---|---|
JsonWebKey |
Representa uma chave criptográfica (simétrica, RSA ou EC). Base para assinatura e criptografia. |
JsonWebKeySet |
Coleção de JsonWebKey – normalmente exposta por provedores em /.well‑known/jwks.json. |
JsonWebKeyStore |
“Cofre” local de chaves utilizado para localizar a chave correta na verificação ou descriptografia. |
JsonWebSignatureBuilder |
Constrói um JWS (e, portanto, um JWT). |
JsonWebEncryptionBuilder |
Constrói um JWE. |
JsonWebToken |
Representa um JWT; contém as claims e pode ser verificado. |
JoseHeader |
Cabeçalho de um JWS ou JWE: inclui algoritmo (alg), identificador da chave (kid) etc. |
import 'package:jose/jose.dart';
import 'dart:convert';
void main() {
// Gera chave RSA 2048 bits para RS256
final jwk = JsonWebKey.generate('RS256');
print('Chave JWK completa:');
print(JsonEncoder.withIndent(' ').convert(jwk.toJson()));
// Criar JWK somente com parte pública
final publicKeyJwk = JsonWebKey.fromJson({
'kty': jwk.keyType,
'alg': jwk.algorithm,
'use': 'sig',
'kid': jwk.keyId,
'n': jwk['n'],
'e': jwk['e'],
});
print('\nChave JWK pública:');
print(JsonEncoder.withIndent(' ').convert(publicKeyJwk.toJson()));
// Exemplo de chave EC (ES256)
final ecJwk = JsonWebKey.generate('ES256');
print('\nChave EC JWK:');
print(JsonEncoder.withIndent(' ').convert(ecJwk.toJson()));
}Por que usar
kid?
O Key ID permite identificar rapidamente qual chave usar durante rotação de chaves.
import 'package:jose/jose.dart';
import 'dart:convert';
Future<void> main() async {
// 1) Gera chave de assinatura
final signingKey = JsonWebKey.generate('RS256');
// 2) Define claims
final claims = JsonWebTokenClaims.fromJson({
'iss': 'https://my-auth-server.com',
'sub': 'user-123',
'aud': ['my-api', 'another-service'],
'exp': DateTime.now().add(Duration(hours: 1)).millisecondsSinceEpoch ~/ 1000,
'iat': DateTime.now().millisecondsSinceEpoch ~/ 1000,
'name': 'John Doe',
'admin': true,
});
// 3) Constrói JWS/JWT
final builder = JsonWebSignatureBuilder()
..jsonContent = claims.toJson()
..addRecipient(signingKey, algorithm: 'RS256');
final jws = builder.build();
final token = jws.toCompactSerialization();
print('JWT gerado:\n$token');
// 4) Verifica token (usando somente a chave pública)
final publicKey = JsonWebKey.fromJson(
Map.of(signingKey.toJson())..removeWhere((k, _) => ['d', 'p', 'q'].contains(k)),
);
final keyStore = JsonWebKeyStore()..addKey(publicKey);
final jwt = await JsonWebToken.decodeAndVerify(token, keyStore);
if (jwt.isVerified == true) {
print('\nToken verificado!');
final issues = jwt.claims.validate(
issuer: Uri.parse('https://my-auth-server.com'),
clientId: 'my-api',
);
print(issues.isEmpty ? 'Claims OK' : 'Problemas: $issues');
}
}O provedor oferece:
- Endpoint JWKS –
/.well-known/jwks.json - Endpoint de emissão de id_token –
/token
import 'package:jose/jose.dart';
import 'dart:convert';
// ---------- Servidor OIDC ----------
final JsonWebKey serverSigningKey = JsonWebKey.generate('RS256')
..['use'] = 'sig'
..['kid'] = 'key-01-2023';
const issuerUrl = 'https://my-simple-oidc-provider.com';
// JWKS endpoint
String jwksResponse() {
final pubKey = JsonWebKey.fromJson(
Map.of(serverSigningKey.toJson())..removeWhere((k, _) => ['d', 'p', 'q'].contains(k)),
);
return JsonWebKeySet.fromKeys([pubKey]).toJson();
}
// Emite id_token
String issueIdToken(String userId, String clientId) {
final claims = JsonWebTokenClaims.fromJson({
'iss': issuerUrl,
'sub': userId,
'aud': [clientId],
'exp': DateTime.now().add(Duration(minutes: 30)).millisecondsSinceEpoch ~/ 1000,
'iat': DateTime.now().millisecondsSinceEpoch ~/ 1000,
'nonce': 'random-nonce',
});
final builder = JsonWebSignatureBuilder()
..jsonContent = claims.toJson()
..addRecipient(serverSigningKey, algorithm: 'RS256');
return builder.build().toCompactSerialization();
}
// ---------- Cliente ----------
Future<void> validate(String idToken) async {
final keySet = JsonWebKeySet.fromJson(json.decode(jwksResponse()));
final keyStore = JsonWebKeyStore()..addKeySet(keySet);
final jwt = await JsonWebToken.decodeAndVerify(idToken, keyStore);
if (jwt.isVerified == true) {
final issues = jwt.claims.validate(
issuer: Uri.parse(issuerUrl),
clientId: 'my-awesome-app',
);
print(issues.isEmpty ? 'Token válido!' : 'Issues: $issues');
}
}
// ---------- Execução ----------
Future<void> main() async {
final token = issueIdToken('user-jane-doe', 'my-awesome-app');
await validate(token);
}- Servidor gera/par de chaves e disponibiliza a parte pública em
/.well‑known/jwks.json. - Cliente busca o JWKS, verifica a assinatura do
id_tokene valida claims (exp, aud, iss…). - Durante rotação de chaves, um novo
kidé publicado — clientes continuam funcionando sem mudanças de código.
⚠️ Segurança em produção
- Armazene chaves privadas em cofres seguros (HSM, KMS, Secret Manager).
- Use HTTPS em todos os endpoints.
- Faça rotação periódica de chaves e valide claims estritamente.
- RFC 7515, RFC 7516, RFC 7517, RFC 7518, RFC 7519
- Dart jose: https://pub.dev/packages/jose