aboutsummaryrefslogtreecommitdiffhomepage
path: root/Example/Database/Tests/Helpers/FTestAuthTokenGenerator.m
blob: bd98e82f096454e4e86b77f41b9253932d3c2a18 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
 * Copyright 2017 Google
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#import <CommonCrypto/CommonHMAC.h>
#import "FTestAuthTokenGenerator.h"
#import "Base64.h"

@implementation FTestAuthTokenGenerator

+ (NSString *) jsonStringForData:(id)data {
    NSData* jsonData = [NSJSONSerialization dataWithJSONObject:data
                                                       options:kNilOptions error:nil];

    return [[NSString alloc] initWithData:jsonData
                                           encoding:NSUTF8StringEncoding];
}

+ (NSNumber *) tokenVersion {
    return @0;
}

+ (NSMutableDictionary *) createOptionsClaims:(NSDictionary *)options {
    NSMutableDictionary* claims = [[NSMutableDictionary alloc] init];
    if (options) {
        NSDictionary* map = @{
            @"expires": @"exp",
            @"notBefore": @"nbf",
            @"admin": @"admin",
            @"debug": @"debug",
            @"simulate": @"simulate"
        };

        for (NSString* claim in map) {
            if (options[claim] != nil) {
                NSString* claimName = [map objectForKey:claim];
                id val = [options objectForKey:claim];
                [claims setObject:val forKey:claimName];
            }
        }
    }
    return claims;
}

+ (NSString *) webSafeBase64:(NSString *)encoded {
    return [[[encoded stringByReplacingOccurrencesOfString:@"=" withString:@""] stringByReplacingOccurrencesOfString:@"+" withString:@"-"] stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
}

+ (NSString *) base64EncodeString:(NSString *)target {
    return [self webSafeBase64:[target base64EncodedString]];
}

+ (NSString *) tokenWithClaims:(NSDictionary *)claims andSecret:(NSString *)secret {
    NSDictionary* headerData = @{@"typ": @"JWT", @"alg": @"HS256"};
    NSString* encodedHeader = [self base64EncodeString:[self jsonStringForData:headerData]];
    NSString* encodedClaims = [self base64EncodeString:[self jsonStringForData:claims]];

    NSString* secureBits = [NSString stringWithFormat:@"%@.%@", encodedHeader, encodedClaims];

    const char *cKey = [secret cStringUsingEncoding:NSUTF8StringEncoding];
    const char *cData = [secureBits cStringUsingEncoding:NSUTF8StringEncoding];
    unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
    NSData* hmac = [NSData dataWithBytesNoCopy:cHMAC length:CC_SHA256_DIGEST_LENGTH freeWhenDone:NO];
    NSString* encodedHmac = [self webSafeBase64:[hmac base64EncodedString]];
    return [NSString stringWithFormat:@"%@.%@.%@", encodedHeader, encodedClaims, encodedHmac];
}

+ (NSString *) tokenWithSecret:(NSString *)secret authData:(NSDictionary *)data andOptions:(NSDictionary *)options {
    NSMutableDictionary* claims = [self createOptionsClaims:options];
    [claims setObject:[self tokenVersion] forKey:@"v"];
    NSNumber* now = [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]];
    [claims setObject:now forKey:@"iat"];
    [claims setObject:data forKey:@"d"];
    return [self tokenWithClaims:claims andSecret:secret];
}

@end