### Install JWT with Carthage Source: https://context7.com/yourkarma/jwt/llms.txt Add the JWT library to your project's Cartfile for installation via Carthage. ```bash github "yourkarma/JWT" "master" ``` -------------------------------- ### Install JWT with CocoaPods Source: https://context7.com/yourkarma/jwt/llms.txt Add the JWT library to your project's Podfile for installation via CocoaPods. ```ruby pod "JWT" ``` -------------------------------- ### Register Custom Claim with Serializer and Verifier Source: https://github.com/yourkarma/jwt/blob/master/README.md Demonstrates the process of defining, serializing, and verifying custom claims within a JWT. Requires setup of a ClaimsSetCoordinator with custom claim logic. ```objective-c - (void)test { /// Setup ClaimsSetCoordinator __auto_type claim = JWTClaimVariations.intersectionOfIntervals; __auto_type claimSerializer = JWTClaimSerializerVariations.interval; __auto_type claimVerifier = JWTClaimVerifierVariations.intersection; id claimsSetCoordinator = [JWTClaimsSetCoordinatorBase new]; [claimsSetCoordinator registerClaim:claim serializer:claimSerializer verifier:claimVerifier forClaimName:JWTClaimsNames.intersectionOfIntervals]; __auto_type deserialized = ({ claimsSetCoordinator.configureClaimsSet(^JWTClaimsSetDSLBase *(JWTClaimsSetDSLBase *claimsSetDSL) { claimsSetDSL.intersection = @[@(2), @(5)]; return claimsSetDSL; }); self.claimsSetCoordinator.claimsSetStorage; }); __auto_type serialized = ({ __auto_type dictionary = [self.claimsSetCoordinator.claimsSetSerializer dictionaryFromClaimsSet:deserialized]; dictionary; }); __auto_type result = @{ JWTClaimsNames.intersectionOfIntervals : @"2,5" }; XCTAssertEqual(serialized.count, 1); XCTAssertEqualObjects(serialized, result); } ``` -------------------------------- ### JWT Encoding and Decoding with Custom Claims Source: https://github.com/yourkarma/jwt/blob/master/Documentation/Prerelease/custom_claims.md Demonstrates encoding and decoding JWTs using a claims set coordinator, including standard claims like issuer, subject, and audience, and custom headers. This example shows the full lifecycle of JWT creation and verification. ```objective-c - (void)testEncodingAndDecodingViaCoordinator { id claimsSetCoordinator = [JWTClaimsSetCoordinatorBase new]; __auto_type claimsSetDSL = claimsSetCoordinator.dslDesrciption; claimsSetDSL.issuer = @"Facebook"; claimsSetDSL.subject = @"Token"; claimsSetDSL.audience = @"https://jwt.io"; claimsSetCoordinator.claimsSetStorage = claimsSetDSL.claimsSetStorage; __auto_type secret = @"secret"; __auto_type algorithmName = @"HS384"; __auto_type headers = @{@"custom":@"value"}; idholder = [JWTAlgorithmHSFamilyDataHolder new].algorithmName(algorithmName).secret(secret); JWTCodingResultType *result = [JWTEncodingBuilder encodeClaimsSetWithCoordinator:claimsSetCoordinator].headers(headers).addHolder(holder).result; NSString *encodedToken = result.successResult.encoded; if (result.successResult) { NSLog(@"encoded result: %@", result.successResult.encoded); } else { NSLog(@"encode failed, error: %@", result.errorResult.error); } __auto_type trustedClaimsSet = claimsSetDSL.claimsSetStorage; NSNumber *options = @(JWTCodingDecodingOptionsNone); NSString *yourJwt = encodedToken; JWTCodingResultType *decodedResult = [JWTDecodingBuilder decodeMessage:yourJwt].claimsSetCoordinator(claimsSetCoordinator).addHolder(holder).options(options).and.result; if (decodedResult.successResult) { NSLog(@"decoded result: %@", decodedResult.successResult.headerAndPayloadDictionary); NSLog(@"headers: %@", decodedResult.successResult.headers); NSLog(@"payload: %@", decodedResult.successResult.payload); NSLog(@"trustedClaimsSet: %@", [claimsSetCoordinator.claimsSetSerializer dictionaryFromClaimsSet:trustedClaimsSet]); NSLog(@"decodedClaimsSet: %@", [claimsSetCoordinator.claimsSetSerializer dictionaryFromClaimsSet:decodedResult.successResult.claimsSetStorage]); } else { NSLog(@"decode failed, error: %@", decodedResult.errorResult.error); } } ``` -------------------------------- ### Register Custom JWT Claim with Serializer and Verifier Source: https://context7.com/yourkarma/jwt/llms.txt This example demonstrates how to register a custom JWT claim, including its serialization and verification logic. It defines a custom claim name, a claim subclass, a serializer for converting between an array and a comma-separated string, and a verifier for checking interval overlap. Finally, it registers these components with the claims coordinator and uses them to encode and decode a JWT. ```objc // 1. Define claim name category @interface JWTClaimsNames (Custom) @property (copy, nonatomic, readonly, class) NSString *intersectionOfIntervals; @end @implementation JWTClaimsNames (Custom) + (NSString *)intersectionOfIntervals { return @"intersectionOfIntervals"; } @end // 2. Define claim subclass @interface JWTClaimCustomIntersection : JWTClaimBase @end @implementation JWTClaimCustomIntersection + (NSString *)name { return JWTClaimsNames.intersectionOfIntervals; } @end // 3. Define serializer (NSArray <-> "min,max" string) @interface JWTClaimSerializerInterval : JWTClaimSerializerBase @end @implementation JWTClaimSerializerInterval - (NSObject *)deserializedClaimValue:(NSObject *)value forName:(NSString *)name { if ([value isKindOfClass:NSString.class]) { NSArray *parts = [(NSString *)value componentsSeparatedByString:@","]; NSMutableArray *nums = [NSMutableArray array]; for (NSString *p in parts) { [nums addObject:@(p.integerValue)]; } return [nums sortedArrayUsingSelector:@selector(compare:)]; } return value; } - (NSObject *)serializedClaimValue:(id)claim { if ([claim.value isKindOfClass:NSArray.class]) { return [(NSArray *)claim.value componentsJoinedByString:@","]; } return claim.value; } @end // 4. Define verifier (non-empty intersection check) @interface JWTClaimVerifierIntersection : JWTClaimVerifierBase @end @implementation JWTClaimVerifierIntersection - (BOOL)verifyValue:(NSObject *)value withTrustedValue:(NSObject *)trustedValue { if ([value isKindOfClass:NSArray.class] && [trustedValue isKindOfClass:NSArray.class]) { NSArray *v = (NSArray *)value, *t = ( NSArray *)trustedValue; if (t.count == 2 && v.count >= 1) { NSInteger lo = [t[0] integerValue], hi = [t[1] integerValue]; NSInteger a = [v[0] integerValue], b = (v.count > 1) ? [v[1] integerValue] : a; return (a <= hi && b >= lo); // intervals overlap } } return NO; } @end // 5. Register and use id coordinator = [JWTClaimsSetCoordinatorBase new]; [coordinator registerClaim:[JWTClaimCustomIntersection new] serializer:[JWTClaimSerializerInterval new] verifier:[JWTClaimVerifierIntersection new] forClaimName:JWTClaimsNames.intersectionOfIntervals]; coordinator.configureClaimsSet(^JWTClaimsSetDSLBase *(JWTClaimsSetDSLBase *dsl) { [dsl dslSetValue:@[@2, @5] forName:JWTClaimsNames.intersectionOfIntervals]; return dsl; }); id holder = [JWTAlgorithmHSFamilyDataHolder new].algorithmName(@"HS256").secret(@"secret"); JWTCodingResultType *encoded = [JWTEncodingBuilder encodeClaimsSetWithCoordinator:coordinator].addHolder(holder).result; // Encoded payload contains: { "intersectionOfIntervals": "2,5" } JWTCodingResultType *decoded = [JWTDecodingBuilder decodeMessage:encoded.successResult.encoded] .claimsSetCoordinator(coordinator) .addHolder(holder) .result; NSLog(@"Custom claim decoded: %@", decoded.successResult.payload); ``` -------------------------------- ### JWTEncodingBuilder — Encode a Payload Dictionary (Version 3) Source: https://context7.com/yourkarma/jwt/llms.txt Demonstrates how to use JWTEncodingBuilder to encode a payload dictionary into a JWT. It shows the setup of the algorithm data holder and how to retrieve the resulting token. ```APIDOC ## JWTEncodingBuilder — Encode a Payload Dictionary (Version 3) `JWTEncodingBuilder` is the primary encoding entry point in the Version 3 API. It accepts an arbitrary payload dictionary, attaches an algorithm data holder (which bundles both the algorithm and the secret), and produces a `JWTCodingResultType` that carries either a signed token string or a structured error. ```objc #import NSDictionary *payload = @{@"sub": @"user_42", @"role": @"admin", @"iat": @([[NSDate date] timeIntervalSince1970])}; NSString *secret = @"my-hs256-secret"; id holder = [JWTAlgorithmHSFamilyDataHolder new] .algorithmName(JWTAlgorithmNameHS256) .secret(secret); JWTCodingResultType *result = [JWTEncodingBuilder encodePayload:payload] .addHolder(holder) .result; if (result.successResult) { NSString *token = result.successResult.encoded; NSLog(@"Token: %@", token); // Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzQyIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNjkwMDAwMDAwfQ. } else { NSLog(@"Encoding error: %@", result.errorResult.error); } ``` ``` -------------------------------- ### Testing Custom Claims Integration Source: https://github.com/yourkarma/jwt/blob/master/Documentation/Prerelease/custom_claims.md Tests the integration of custom claims, specifically the 'intersectionOfIntervals' claim, using the JWT claims set coordinator. This example demonstrates setting, serializing, and verifying custom claims. ```objective-c - (void)test { __auto_type claim = JWTClaimVariations.intersectionOfIntervals; __auto_type claimSerializer = JWTClaimSerializerVariations.interval; __auto_type claimVerifier = JWTClaimVerifierVariations.intersection; id claimsSetCoordinator = [JWTClaimsSetCoordinatorBase new]; [claimsSetCoordinator registerClaim:claim serializer:claimSerializer verifier:claimVerifier forClaimName:JWTClaimsNames.intersectionOfIntervals]; __auto_type deserialized = ({ claimsSetCoordinator.configureClaimsSet(^JWTClaimsSetDSLBase *(JWTClaimsSetDSLBase *claimsSetDSL) { claimsSetDSL.intersection = @[@(2), @(5)]; return claimsSetDSL; }); self.claimsSetCoordinator.claimsSetStorage; }); __auto_type serialized = ({ __auto_type dictionary = [self.claimsSetCoordinator.claimsSetSerializer dictionaryFromClaimsSet:deserialized]; dictionary; }); __auto_type result = @{ JWTClaimsNames.intersectionOfIntervals : @"2,5" }; XCTAssertEqual(serialized.count, 1); XCTAssertEqualObjects(serialized, result); } ``` -------------------------------- ### Load PEM Keys and Sign/Verify JWT Source: https://github.com/yourkarma/jwt/blob/master/README.md Demonstrates how to load public and private keys from PEM files and use them for signing and verifying JWTs. Ensure PEM files are correctly formatted and accessible. ```Objective-C // Load keys - (NSString *)pemKeyStringFromFileWithName:(NSString *)string inBundle:(NSBundle *)bundle { NSURL *fileURL = [bundle URLForResource:name withExtension:@"pem"]; NSError *error = nil; NSString *fileContent = [NSString stringWithContentsOfURL:fileURL encoding:NSUTF8StringEncoding error:&error]; if (error) { NSLog(@"%@ error: %@", self.debugDescription, error); return nil; } } // Sign and verify - (void)signAndVerifyWithPrivateKeyPemString:(NSString *)privateKey publicKeyPemString:(NSString *)publicKey privateKeyPassphrase:(NSString *)passphrase { NSString *algorithmName = @"RS256"; id signDataHolder = [JWTAlgorithmRSFamilyDataHolder new].keyExtractorType([JWTCryptoKeyExtractor privateKeyWithPEMBase64].type).privateKeyCertificatePassphrase(passphrase).algorithmName(algorithmName).secret(privateKey); id verifyDataHolder = [JWTAlgorithmRSFamilyDataHolder new].keyExtractorType([JWTCryptoKeyExtractor publicKeyWithPEMBase64].type).algorithmName(algorithmName).secret(publicKey); // sign NSDictionary *payloadDictionary = @{@"hello": @"world"}; JWTCodingBuilder *signBuilder = [JWTEncodingBuilder encodePayload:payloadDictionary].addHolder(signDataHolder); JWTCodingResultType *signResult = signBuilder.result; NSString *token = nil; if (signResult.successResult) { // success NSLog(@"%@ success: %@", self.debugDescription, signResult.successResult.encoded); token = signResult.successResult.encoded; } else { // error NSLog(@"%@ error: %@", self.debugDescription, signResult.errorResult.error); } // verify if (token == nil) { NSLog(@"something wrong"); } JWTCodingBuilder *verifyBuilder = [JWTDecodingBuilder decodeMessage:token].addHolder(verifyDataHolder); JWTCodingResultType *verifyResult = verifyBuilder.result; if (verifyResult.successResult) { // success NSLog(@"%@ success: %@", self.debugDescription, verifyResult.successResult.payload); token = verifyResult.successResult.encoded; } else { // error NSLog(@"%@ error: %@", self.debugDescription, verifyResult.errorResult.error); } } ``` -------------------------------- ### Initialize EC Crypto Keys for JWT Source: https://github.com/yourkarma/jwt/blob/master/README.md Shows how to initialize private and public keys for EC algorithms using PEM encoded strings. Specify the key type as EC using parameters. ```objective-c NSString *privateKeyString = @""; NSString *publicKeyString = @""; // Note: We should pass type of key. Default type is RSA. NSDictionary *parameters = @{JWTCryptoKey.parametersKeyBuilder : JWTCryptoKeyBuilder.new.keyTypeEC}; id privateKey = [[JWTCryptoKeyPrivate alloc] initWithPemEncoded:privateKeyString parameters:parameters error:nil]; id publicKey = [[JWTCryptoKeyPublic alloc] initWithPemEncoded:publicKeyString parameters:parameters error:nil]; // Note: JWTAlgorithmRSFamilyDataHolder will be renamed to something more appropriate. It can holds any asymmetric keys pair (private and public). id holder = [JWTAlgorithmRSFamilyDataHolder new].signKey(privateKey).verifyKey(publicKey).algorithmName(JWTAlgorithmNameES256); ``` -------------------------------- ### RS256 JWT Encoding and Decoding with P12 Key Source: https://github.com/yourkarma/jwt/blob/master/README.md Illustrates how to encode a JWT using the RS256 algorithm with a private key from a P12 file and its passphrase. Also shows how to decode the JWT using the corresponding public key. ```objective-c // Encode NSDictionary *payload = @{@"payload" : @"hidden_information"}; NSString *algorithmName = @"RS256"; NSString *filePath = [[NSBundle mainBundle] pathForResource:@"secret_key" ofType:@"p12"]; NSData *privateKeySecretData = [NSData dataWithContentsOfFile:filePath]; NSString *passphraseForPrivateKey = @"secret"; JWTBuilder *builder = [JWTBuilder encodePayload:payload].secretData(privateKeySecretData).privateKeyCertificatePassphrase(passphraseForPrivateKey).algorithmName(algorithmName); NSString *token = builder.encode; // check error if (builder.jwtError == nil) { // handle result } else { // error occurred. } // Decode // Suppose, that you get token from previous example. You need a valid public key for a private key in previous example. // Private key stored in @"secret_key.p12". So, you need public key for that private key. NSString *publicKey = @"..."; // load public key. Or use it as raw string. algorithmName = @"RS256"; JWTBuilder *decodeBuilder = [JWTBuilder decodeMessage:token].secret(publicKey).algorithmName(algorithmName); NSDictionary *envelopedPayload = decodeBuilder.decode; // check error if (decodeBuilder.jwtError == nil) { // handle result } else { // error occurred. } ``` -------------------------------- ### Algorithm Whitelist for Decoding Source: https://context7.com/yourkarma/jwt/llms.txt Explains how to use the `whitelist` setter to restrict accepted algorithms during JWT decoding, mitigating algorithm-substitution attacks. ```APIDOC ## Algorithm Whitelist (Version 2) The `whitelist` setter limits which algorithm names are accepted during decoding, preventing algorithm-substitution attacks. ### Rejecting Algorithms ```objc NSString *jwtToken = @"header.payload.signature"; NSString *secret = @"secret"; NSString *algorithmName = @"HS256"; NSArray *whitelist = @[@"HS256", @"HS512"]; // Returns nil — empty whitelist rejects all algorithms NSDictionary *rejected = [JWTBuilder decodeMessage:jwtToken] .secret(secret) .algorithmName(algorithmName) .whitelist(@[]) // nothing is allowed .decode; NSLog(@"Rejected: %@", rejected); // (null) ``` ### Accepting Algorithms ```objc // Returns the decoded payload — HS256 is in the whitelist NSDictionary *accepted = [JWTBuilder decodeMessage:jwtToken] .secret(secret) .algorithmName(algorithmName) .whitelist(whitelist) .decode; NSLog(@"Accepted: %@", accepted); // { header = {...}; payload = {...} } ``` ``` -------------------------------- ### Look Up JWT Algorithm by Name Source: https://context7.com/yourkarma/jwt/llms.txt JWTAlgorithmFactory provides a registry for built-in JWT algorithms. Custom algorithms can be integrated by implementing the JWTAlgorithm protocol. ```objc // Enumerate all registered algorithms NSArray> *all = JWTAlgorithmFactory.algorithms; for (id alg in all) { NSLog(@"Available algorithm: %@", alg.name); } // Available algorithm: HS256 // Available algorithm: HS384 // Available algorithm: HS512 // Available algorithm: RS256 // Available algorithm: RS384 // Available algorithm: RS512 // Available algorithm: ES256 // Available algorithm: none // Look up by name id hs256 = [JWTAlgorithmFactory algorithmByName:@"HS256"]; // Use in Version 2 builder [JWTBuilder encodePayload:@{@"foo": @"bar"}] .secret(@"secret") .algorithm(hs256) .encode; ``` -------------------------------- ### RS256 Encoding and Decoding with PKCS12 File Source: https://context7.com/yourkarma/jwt/llms.txt Demonstrates how to encode and decode JWTs using the RS256 algorithm with a PKCS12 (.p12) file for signing and verification. ```APIDOC ## RS256 via PKCS12 (.p12) File — Version 2 Builder Style The Version 2 `JWTBuilder` API provides a simpler interface when only a single algorithm and secret are needed. It is still supported and is convenient for RS256 with `.p12` certificate files. ### Encode ```objc // --- Encode --- NSDictionary *payload = @{@"payload": @"hidden_information"}; NSString *p12Path = [[NSBundle mainBundle] pathForResource:@"secret_key" ofType:@"p12"]; NSData *p12Data = [NSData dataWithContentsOfFile:p12Path]; JWTBuilder *encodeBuilder = [JWTBuilder encodePayload:payload] .secretData(p12Data) .privateKeyCertificatePassphrase(@"secret") .algorithmName(@"RS256"); NSString *token = encodeBuilder.encode; if (encodeBuilder.jwtError == nil) { NSLog(@"Token: %@", token); } else { NSLog(@"Encode error: %@", encodeBuilder.jwtError); } ``` ### Decode ```objc // --- Decode --- NSString *publicKey = @"MIICnTCCAYU..."; // PEM or raw public key string JWTBuilder *decodeBuilder = [JWTBuilder decodeMessage:token] .secret(publicKey) .algorithmName(@"RS256"); NSDictionary *decoded = decodeBuilder.decode; if (decodeBuilder.jwtError == nil) { NSLog(@"Decoded payload: %@", decoded[@"payload"]); } else { NSLog(@"Decode error: %@", decodeBuilder.jwtError); } ``` ``` -------------------------------- ### JWTDecodingBuilder — Decode and Verify a Token (Version 3) Source: https://context7.com/yourkarma/jwt/llms.txt Illustrates how to use JWTDecodingBuilder to decode and verify a JWT string. It covers setting up the algorithm holder, specifying decoding options, and handling the success or error results. ```APIDOC ## JWTDecodingBuilder — Decode and Verify a Token (Version 3) `JWTDecodingBuilder` decodes a JWT string, verifies its signature against the supplied holder, and returns the headers and payload in a typed result object. Signature verification is on by default; pass `JWTCodingDecodingOptionsSkipVerification` to disable it (debug only). ```objc NSString *token = @"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."; NSString *secret = @"my-hs256-secret"; id holder = [JWTAlgorithmHSFamilyDataHolder new] .algorithmName(JWTAlgorithmNameHS256) .secret(secret); NSNumber *options = @(JWTCodingDecodingOptionsNone); // normal verified decode JWTCodingResultType *result = [JWTDecodingBuilder decodeMessage:token] .addHolder(holder) .options(options) .and .result; if (result.successResult) { NSLog(@"Headers: %@", result.successResult.headers); NSLog(@"Payload: %@", result.successResult.payload); // Payload: { sub = user_42; role = admin; iat = 1690000000; } } else { NSLog(@"Decoding error: %@", result.errorResult.error); } ``` ``` -------------------------------- ### JWTBuilder Version 2 Fluent Encoding/Decoding with JWTClaimsSet Source: https://context7.com/yourkarma/jwt/llms.txt Shows how to use the JWTBuilder for encoding and decoding JWTs with HMAC algorithms, supporting custom claims and header modifications. ```APIDOC ## JWTBuilder — Version 2 Fluent Encoding / Decoding with JWTClaimsSet The Version 2 `JWTBuilder` supports HMAC algorithms with a plain string secret and the full `JWTClaimsSet` model including registered claims and header customisation. ### Encode ```objc // --- Encode --- JWTClaimsSet *claimsSet = [[JWTClaimsSet alloc] init]; claimsSet.issuer = @"Facebook"; claimsSet.subject = @"Token"; claimsSet.audience = @"http://yourkarma.com"; claimsSet.expirationDate = [NSDate dateWithTimeIntervalSinceNow:3600]; claimsSet.notBeforeDate = [NSDate date]; claimsSet.issuedAt = [NSDate date]; claimsSet.identifier = @"unique-jwt-id"; NSString *secret = @"secret"; NSString *algorithmName = @"HS384"; JWTBuilder *encodeBuilder = [JWT encodeClaimsSet:claimsSet]; NSString *encodedJWT = encodeBuilder .secret(secret) .algorithmName(algorithmName) .headers(@{@"custom": @"value"}) .encode; if (encodeBuilder.jwtError == nil) { NSLog(@"Encoded: %@", encodedJWT); } ``` ### Decode with Claims Verification ```objc // --- Decode with claims verification --- JWTClaimsSet *trustedClaimsSet = [claimsSet copy]; JWTBuilder *decodeBuilder = [JWT decodeMessage:encodedJWT]; NSDictionary *decodedResult = decodeBuilder .message(encodedJWT) .secret(secret) .algorithmName(algorithmName) .claimsSet(trustedClaimsSet) .options(@(NO)) // NO = verify signature; YES = skip (debug only) .decode; if (decodeBuilder.jwtError == nil) { NSLog(@"Header: %@", decodedResult[@"header"]); NSLog(@"Payload: %@", decodedResult[@"payload"]); } else { NSLog(@"Error: %@", decodeBuilder.jwtError); } ``` ``` -------------------------------- ### Encode and Decode JWT with Algorithm Chain Source: https://github.com/yourkarma/jwt/blob/master/README.md Demonstrates encoding a JWTClaimsSet with custom headers and a specific algorithm holder, then decoding the resulting token using the same holder. Ensure the correct options are set for decoding. ```objective-c JWTClaimsSet *claimsSet = [[JWTClaimsSet alloc] init]; // fill it claimsSet.issuer = @"Facebook"; claimsSet.subject = @"Token"; claimsSet.audience = @"https://jwt.io"; // encode it NSString *secret = @"secret"; NSString *algorithmName = @"HS384"; NSDictionary *headers = @{@"custom":@"value"}; idholder = [JWTAlgorithmHSFamilyDataHolder new].algorithmName(algorithmName).secret(secret); JWTCodingResultType *result = [JWTEncodingBuilder encodeClaimsSet:claimsSet].headers(headers).addHolder(holder).result; NSString *encodedToken = result.successResult.encoded; if (result.successResult) { // handle encoded result NSLog(@"encoded result: %@", result.successResult.encoded); } else { // handle error NSLog(@"encode failed, error: %@", result.errorResult.error); } // decode it // you can set any property that you want, all properties are optional JWTClaimsSet *trustedClaimsSet = [claimsSet copy]; NSNumber *options = @(JWTCodingDecodingOptionsNone); NSString *yourJwt = encodedToken; // from previous example JWTCodingResultType *decodedResult = [JWTDecodingBuilder decodeMessage:yourJwt].claimsSet(claimsSet).addHolder(holder).options(options).and.result; if (decodedResult.successResult) { // handle decoded result NSLog(@"decoded result: %@", decodedResult.successResult.headerAndPayloadDictionary); NSLog(@"headers: %@", decodedResult.successResult.headers); NSLog(@"payload: %@", decodedResult.successResult.payload); } else { // handle error NSLog(@"decode failed, error: %@", decodedResult.errorResult.error); } ``` -------------------------------- ### Construct JWTCryptoKey from PEM and PKCS12 Source: https://context7.com/yourkarma/jwt/llms.txt JWTCryptoKeyPublic and JWTCryptoKeyPrivate wrap SecKeyRef and can be initialized from various formats. Attach them to an JWTAlgorithmRSFamilyDataHolder. ```objc NSError *keyError = nil; // EC public key from PEM NSDictionary *ecParams = @{JWTCryptoKey.parametersKeyBuilder: JWTCryptoKeyBuilder.new.keyTypeEC}; JWTCryptoKeyPublic *pubKey = [[JWTCryptoKeyPublic alloc] initWithPemEncoded:@"-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----" parameters:ecParams error:&keyError]; if (keyError) { NSLog(@"Key load error: %@", keyError); } // RSA private key from PKCS12 data NSData *p12 = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"key" ofType:@"p12"]]; JWTCryptoKeyPrivate *privKey = [[JWTCryptoKeyPrivate alloc] initWithP12Data:p12 withPassphrase:@"passphrase" parameters:nil error:&keyError]; // Verify key is valid JWTCryptoKeyPublic *checked = [pubKey checkedWithError:&keyError]; if (keyError) { NSLog(@"Invalid key: %@", keyError); } // Attach to holder id holder = [JWTAlgorithmRSFamilyDataHolder new] .signKey(privKey) .verifyKey(checked) .algorithmName(@"RS256"); ``` -------------------------------- ### Algorithm Whitelisting for JWT Decoding Source: https://context7.com/yourkarma/jwt/llms.txt Implement algorithm whitelisting to prevent algorithm-substitution attacks during JWT decoding. An empty whitelist will reject all algorithms. ```objc NSString *jwtToken = @"header.payload.signature"; NSString *secret = @"secret"; NSString *algorithmName = @"HS256"; NSArray *whitelist = @[@"HS256", @"HS512"]; // Returns nil — empty whitelist rejects all algorithms NSDictionary *rejected = [JWTBuilder decodeMessage:jwtToken] .secret(secret) .algorithmName(algorithmName) .whitelist(@[]) // nothing is allowed .decode; // Returns the decoded payload — HS256 is in the whitelist NSDictionary *accepted = [JWTBuilder decodeMessage:jwtToken] .secret(secret) .algorithmName(algorithmName) .whitelist(whitelist) .decode; NSLog(@"Rejected: %@", rejected); // (null) NSLog(@"Accepted: %@", accepted); // { header = {...}; payload = {...} } ``` -------------------------------- ### Serializer for Interval Claims Source: https://github.com/yourkarma/jwt/blob/master/Documentation/Prerelease/custom_claims.md Handles the conversion of interval data between its string representation (e.g., "1,5") and an array of integers. This is useful for claims that need a specific serialization format. ```objective-c /// Define a serializer @interface JWTClaimSerializerForInterval : JWTClaimSerializerBase @end @implementation JWTClaimSerializerForInterval - (NSObject *)deserializedClaimValue:(NSObject *)value forName:(NSString *)name { if ([value isKindOfClass:NSString.class]) { __auto_type array = [(NSString *)value componentsSeparatedByString:@","]; __auto_type result = [NSMutableArray array]; for (NSString *item in array) { [result addObject:@(item.integerValue)]; } __auto_type descriptor = [[NSSortDescriptor alloc] initWithKey:@"integerValue" ascending:YES]; return [result sortedArrayUsingDescriptors:@[descriptor]]; } return value; } - (NSObject *)serializedClaimValue:(id)claim { __auto_type value = claim.value; if ([value isKindOfClass:NSArray.class]) { __auto_type descriptor = [[NSSortDescriptor alloc] initWithKey:@"integerValue" ascending:YES]; __auto_type sortedArray = [(NSArray *)claim.value sortedArrayUsingDescriptors:@[descriptor]]; return [sortedArray componentsJoinedByString:@","]; } return value; } @end ``` -------------------------------- ### Enforce Algorithm Whitelist for Decoding Source: https://github.com/yourkarma/jwt/blob/master/README.md Use the whitelist option to restrict decoding to a specific set of allowed algorithms. An empty whitelist will result in nil. ```objective-c NSArray *whitelist = @[@"HS256", @"HS512"]; NSString *jwtToken = @"header.payload.signature"; NSString *secret = @"secret"; NSString *algorithmName = @"HS256"; //Returns nil NSDictionary *payload = [JWTBuilder decodeMessage:jwtToken].secret(secret).algorithmName(algorithmName).whitelist(@[]).decode; //Returns the decoded payload NSDictionary *payload = [JWTBuilder decodeMessage:jwtToken].secret(secret).algorithmName(algorithmName).whitelist(whitelist).decode; ``` -------------------------------- ### Encode and Decode JWT with ClaimsSet Verification Source: https://context7.com/yourkarma/jwt/llms.txt Demonstrates encoding a JWT with a claims set and then decoding it while verifying the claims against a coordinator. Ensure the JWTClaimsSetCoordinator is properly configured before encoding and decoding. ```objc // --- Encoding with ClaimsSetCoordinator --- id coordinator = [JWTClaimsSetCoordinatorBase new]; JWTClaimsSetDSLBase *dsl = coordinator.dslDesrciption; dsl.issuer = @"my-service"; dsl.subject = @"user_42"; dsl.audience = @"https://api.example.com"; coordinator.claimsSetStorage = dsl.claimsSetStorage; id holder = [JWTAlgorithmHSFamilyDataHolder new] .algorithmName(@"HS384") .secret(@"supersecret"); JWTCodingResultType *encodeResult = [JWTEncodingBuilder encodeClaimsSetWithCoordinator:coordinator] .headers(@{@"kid": @"key-1"}) .addHolder(holder) .result; NSString *token = encodeResult.successResult.encoded; // --- Decoding with claims verification --- JWTCodingResultType *decodeResult = [JWTDecodingBuilder decodeMessage:token] .claimsSetCoordinator(coordinator) // validates decoded claims .addHolder(holder) .options(@(JWTCodingDecodingOptionsNone)) .and .result; if (decodeResult.successResult) { NSLog(@"payload: %@", decodeResult.successResult.payload); NSLog(@"claims: %@", [coordinator.claimsSetSerializer dictionaryFromClaimsSet:decodeResult.successResult.claimsSetStorage]); } else { NSLog(@"error: %@", decodeResult.errorResult.error); } ``` -------------------------------- ### RS256 Signing and Verification with PEM Keys Source: https://context7.com/yourkarma/jwt/llms.txt Load PEM-encoded private and public keys from bundle files to sign and verify JWTs using the RS256 algorithm. Ensure the private key is protected by a passphrase if necessary. ```objc // Load PEM content from bundle files (rs256-private.pem / rs256-public.pem) NSBundle *bundle = [NSBundle mainBundle]; NSString *privatePem = [NSString stringWithContentsOfURL:[bundle URLForResource:@"rs256-private" withExtension:@"pem"] encoding:NSUTF8StringEncoding error:nil]; NSString *publicPem = [NSString stringWithContentsOfURL:[bundle URLForResource:@"rs256-public" withExtension:@"pem"] encoding:NSUTF8StringEncoding error:nil]; NSString *passphrase = @"password"; // passphrase protecting the private key // Signing holder (private key via PEM) id signHolder = [JWTAlgorithmRSFamilyDataHolder new] .keyExtractorType([JWTCryptoKeyExtractor privateKeyWithPEMBase64].type) .privateKeyCertificatePassphrase(passphrase) .algorithmName(@"RS256") .secret(privatePem); // Verification holder (public key via PEM) id verifyHolder = [JWTAlgorithmRSFamilyDataHolder new] .keyExtractorType([JWTCryptoKeyExtractor publicKeyWithPEMBase64].type) .algorithmName(@"RS256") .secret(publicPem); // Sign NSDictionary *payload = @{@"sub": @"user_42", @"iss": @"auth-server"}; JWTCodingResultType *signResult = [JWTEncodingBuilder encodePayload:payload] .addHolder(signHolder) .result; NSString *token = nil; if (signResult.successResult) { token = signResult.successResult.encoded; NSLog(@"Signed token: %@", token); } else { NSLog(@"Sign error: %@", signResult.errorResult.error); } // Verify if (token) { JWTCodingResultType *verifyResult = [JWTDecodingBuilder decodeMessage:token] .addHolder(verifyHolder) .result; if (verifyResult.successResult) { NSLog(@"Verified payload: %@", verifyResult.successResult.payload); // Verified payload: { sub = user_42; iss = auth-server; } } else { NSLog(@"Verify error: %@", verifyResult.errorResult.error); } } ``` -------------------------------- ### Populate JWT Algorithm Chain with Multiple Secrets Source: https://github.com/yourkarma/jwt/blob/master/README.md When an algorithm might use several secrets, create a chain and populate it with an array of secret data. This allows the decoding process to try each secret. ```objective-c // possible that your algorithm has several secrets. // you don't know which secret to use. // but you want to decode it. NSString *firstSecret = @"first"; NSArray *manySecrets = @[@"second", @"third", @"forty two"]; // translate to data NSArray *manySecretsData = @[]; for (NSString *secret in manySecrets) { NSData *secretData = [JWTBase64Coder dataWithBase64UrlEncodedString:secret]; if (secret) { manySecretsData = [manySecretsData arrayByAddingObject:secretData]; } } NSString *algorithmName = JWTAlgorithmNameHS384; id firstHolder = [JWTAlgorithmHSFamilyDataHolder new].algorithmName(algorithmName).secret(firstSecret); // lets create chain JWTAlgorithmDataHolderChain *chain = [JWTAlgorithmDataHolderChain chainWithHolder:firstHolder]; // and lets populate chain with secrets. NSLog(@"chain has: %@", chain.debugDescription); JWTAlgorithmDataHolderChain *expandedChain = [chain chainByPopulatingAlgorithm:firstHolder.currentAlgorithm withManySecretData:manySecretsData]; // now we have expanded chain with many secrets and one algorithm. NSLog(@"expanded chain has: %@", expandedChain.debugDescription); ``` -------------------------------- ### Encode and Decode JWT with String Secret Source: https://github.com/yourkarma/jwt/blob/master/README.md Demonstrates encoding a claims set into a JWT and then decoding it using a shared secret string and HS384 algorithm. Includes error handling for both operations. ```objective-c // suppose, that you create ClaimsSet JWTClaimsSet *claimsSet = [[JWTClaimsSet alloc] init]; // fill it claimsSet.issuer = @"Facebook"; claimsSet.subject = @"Token"; claimsSet.audience = @"http://yourkarma.com"; // encode it NSString *secret = @"secret"; NSString *algorithmName = @"HS384"; NSDictionary *headers = @{@"custom":@"value"}; id algorithm = [JWTAlgorithmFactory algorithmByName:algorithmName]; JWTBuilder *encodeBuilder = [JWT encodeClaimsSet:claimsSet]; NSString *encodedResult = encodeBuilder.secret(secret).algorithm(algorithm).headers(headers).encode; if (encodeBuilder.jwtError == nil) { // handle encoded result NSLog(@"encoded result: %@", encodedResult); } else { // handle error NSLog(@"encode failed, error: %@", encodeBuilder.jwtError); } // decode it // you can set any property that you want, all properties are optional JWTClaimsSet *trustedClaimsSet = [claimsSet copy]; // decode forced ? try YES BOOL decodeForced = NO; NSNumber *options = @(decodeForced); NSString *yourJwt = encodedResult; // from previous example NSString *yourSecret = secret; // from previous example NSString *yourAlgorithm = algorithmName; // from previous example JWTBuilder *decodeBuilder = [JWT decodeMessage:yourJwt]; NSDictionary *decodedResult = decodeBuilder.message(yourJwt).secret(yourSecret).algorithmName(yourAlgorithm).claimsSet(trustedClaimsSet).options(options).decode; if (decodeBuilder.jwtError == nil) { // handle decoded result NSLog(@"decoded result: %@", decodedResult); } else { // handle error NSLog(@"decode failed, error: %@", decodeBuilder.jwtError); } ``` -------------------------------- ### Decode and Verify a Token with JWTDecodingBuilder (Version 3) Source: https://context7.com/yourkarma/jwt/llms.txt Use JWTDecodingBuilder to decode and verify a JWT string. Signature verification is enabled by default and requires a matching secret and algorithm. Pass JWTCodingDecodingOptionsSkipVerification to disable verification for debugging purposes. ```objc NSString *token = @"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."; NSString *secret = @"my-hs256-secret"; id holder = [JWTAlgorithmHSFamilyDataHolder new] .algorithmName(JWTAlgorithmNameHS256) .secret(secret); NSNumber *options = @(JWTCodingDecodingOptionsNone); // normal verified decode JWTCodingResultType *result = [JWTDecodingBuilder decodeMessage:token] .addHolder(holder) .options(options) .and .result; if (result.successResult) { NSLog(@"Headers: %@", result.successResult.headers); NSLog(@"Payload: %@", result.successResult.payload); // Payload: { sub = user_42; role = admin; iat = 1690000000; } } else { NSLog(@"Decoding error: %@", result.errorResult.error); } ``` -------------------------------- ### Use JWTAlgorithmDataHolderChain for Multiple Secrets Source: https://context7.com/yourkarma/jwt/llms.txt Illustrates how to use JWTAlgorithmDataHolderChain to attempt decoding a JWT with a list of potential secrets or algorithms. This is useful for secret rotation or when the exact signing secret is unknown. ```objc NSString *token = @"eyJ..."; // token whose signing secret is unknown // Build individual holders for each candidate secret id h1 = [JWTAlgorithmHSFamilyDataHolder new].algorithmName(JWTAlgorithmNameHS384).secret(@"secret-v1"); id h2 = [JWTAlgorithmHSFamilyDataHolder new].algorithmName(JWTAlgorithmNameHS384).secret(@"secret-v2"); id h3 = [JWTAlgorithmHSFamilyDataHolder new].algorithmName(JWTAlgorithmNameHS384).secret(@"secret-v3"); // Compose into a chain JWTAlgorithmDataHolderChain *chain = [[JWTAlgorithmDataHolderChain alloc] initWithHolders:@[h1, h2, h3]]; // Alternatively, start from one holder and expand with many secrets as NSData NSArray *secretsData = @[ [JWTBase64Coder dataWithBase64UrlEncodedString:@"secret-v2"], [JWTBase64Coder dataWithBase64UrlEncodedString:@"secret-v3"] ]; JWTAlgorithmDataHolderChain *expandedChain = [[JWTAlgorithmDataHolderChain chainWithHolder:h1] chainByPopulatingAlgorithm:h1.internalAlgorithm withManySecretData:secretsData]; JWTCodingResultType *result = [JWTDecodingBuilder decodeMessage:token] .chain(expandedChain) .result; if (result.successResult) { NSLog(@"Decoded with one of the secrets: %@", result.successResult.payload); } ``` -------------------------------- ### HMAC Encoding/Decoding with JWTClaimsSet Source: https://context7.com/yourkarma/jwt/llms.txt This snippet is for encoding and decoding JWTs using HMAC algorithms with a plain string secret and the JWTClaimsSet model. It supports custom headers and claims verification. ```objc // --- Encode --- JWTClaimsSet *claimsSet = [[JWTClaimsSet alloc] init]; claimsSet.issuer = @"Facebook"; claimsSet.subject = @"Token"; claimsSet.audience = @"http://yourkarma.com"; claimsSet.expirationDate = [NSDate dateWithTimeIntervalSinceNow:3600]; claimsSet.notBeforeDate = [NSDate date]; claimsSet.issuedAt = [NSDate date]; claimsSet.identifier = @"unique-jwt-id"; NSString *secret = @"secret"; NSString *algorithmName = @"HS384"; JWTBuilder *encodeBuilder = [JWT encodeClaimsSet:claimsSet]; NSString *encodedJWT = encodeBuilder .secret(secret) .algorithmName(algorithmName) .headers(@{@"custom": @"value"}) .encode; if (encodeBuilder.jwtError == nil) { NSLog(@"Encoded: %@", encodedJWT); } // --- Decode with claims verification --- JWTClaimsSet *trustedClaimsSet = [claimsSet copy]; JWTBuilder *decodeBuilder = [JWT decodeMessage:encodedJWT]; NSDictionary *decodedResult = decodeBuilder .message(encodedJWT) .secret(secret) .algorithmName(algorithmName) .claimsSet(trustedClaimsSet) .options(@(NO)) // NO = verify signature; YES = skip (debug only) .decode; if (decodeBuilder.jwtError == nil) { NSLog(@"Header: %@", decodedResult[@"header"]); NSLog(@"Payload: %@", decodedResult[@"payload"]); } else { NSLog(@"Error: %@", decodeBuilder.jwtError); } ``` -------------------------------- ### Create JWT Algorithm Data Holder Chain Source: https://github.com/yourkarma/jwt/blob/master/README.md Use JWTAlgorithmDataHolderChain to chain multiple algorithm data holders. This is useful when an algorithm might return an error, allowing fallback to other holders. ```objective-c // create token NSString *token = @"..."; // possible that algorithm could return error. // you could try use algorithm and data chain. NSString *firstSecret = @"first"; NSString *firstAlgorithmName = JWTAlgorithmNameHS384; id firstHolder = [JWTAlgorithmHSFamilyDataHolder new].algorithmName(firstAlgorithmName).secret(firstSecret); id errorHolder = [JWTAlgorithmNoneDataHolder new]; // chain together. JWTAlgorithmDataHolderChain *chain = [[JWTAlgorithmDataHolderChain alloc] initWithHolders:@[firstHolder, errorHolder]]; // or add them in builder [JWTDecodingBuilder decodeMessage:token].addHolder(firstHolder).addHolder(errorHolder); // or add them as chain [JWTDecodingBuilder decodeMessage:token].chain(chain); ``` -------------------------------- ### Define Custom Claim Name and Class Source: https://github.com/yourkarma/jwt/blob/master/Documentation/Prerelease/custom_claims.md Defines a constant for the custom claim name and a corresponding claim class. Use this when you need to introduce a new, specific claim type to your JWT. ```objective-c /// Define a name of a claim. @interface JWTClaimsNames (Custom) @property (copy, nonatomic, readonly, class) NSString *intersectionOfIntervals; @end @implementation JWTClaimsNames (Custom) + (NSString *)intersectionOfIntervals { return @"intersectionOfIntervals"; } @end /// Define a claim @interface JWTClaimCustomIntersectionOfIntervals : JWTClaimBase @end @implementation JWTClaimCustomIntersectionOfIntervals + (NSString *)name { return JWTClaimsNames.intersectionOfIntervals; } @end ``` -------------------------------- ### RS256 Encoding/Decoding with PKCS12 File Source: https://context7.com/yourkarma/jwt/llms.txt Use this snippet for RS256 JWTs when you have a PKCS12 (.p12) certificate file. Ensure the .p12 file and its passphrase are correct. ```objc // --- Encode --- NSDictionary *payload = @{@"payload": @"hidden_information"}; NSString *p12Path = [[NSBundle mainBundle] pathForResource:@"secret_key" ofType:@"p12"]; NSData *p12Data = [NSData dataWithContentsOfFile:p12Path]; JWTBuilder *encodeBuilder = [JWTBuilder encodePayload:payload] .secretData(p12Data) .privateKeyCertificatePassphrase(@"secret") .algorithmName(@"RS256"); NSString *token = encodeBuilder.encode; if (encodeBuilder.jwtError == nil) { NSLog(@"Token: %@", token); } else { NSLog(@"Encode error: %@", encodeBuilder.jwtError); } // --- Decode --- NSString *publicKey = @"MIICnTCCAYU..."; // PEM or raw public key string JWTBuilder *decodeBuilder = [JWTBuilder decodeMessage:token] .secret(publicKey) .algorithmName(@"RS256"); NSDictionary *decoded = decodeBuilder.decode; if (decodeBuilder.jwtError == nil) { NSLog(@"Decoded payload: %@", decoded[@"payload"]); } else { NSLog(@"Decode error: %@", decodeBuilder.jwtError); } ``` -------------------------------- ### Decode JWT with Whitelisted Algorithms Source: https://github.com/yourkarma/jwt/blob/master/README.md Decode a JWT by specifying a whitelist of allowed algorithms. This is useful when the JWT might be signed with one of several known algorithms. Note the limitation of a single secret for paired algorithms. ```Objective-C NSString *jwtResultOrError = /*...*/; NSString *secret = @"secret"; JWTBuilder *builder = [JWT decodeMessage:jwtResultOrError].secret(@"secret").whitelist(@[@"HS256", @"none"]); NSDictionary *decoded = builder.decode; if (builder.jwtError) { // oh! } else { NSDictionary *payload = decoded[@"payload"]; NSDictionary *header = decoded[@"header"]; NSArray *tries = decoded[@"tries"]; // will be evolded into something appropriate later. } ```