FTestAuthTokenGenerator.m 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * Copyright 2017 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import "FirebaseDatabase/Tests/Helpers/FTestAuthTokenGenerator.h"
  17. #import <CommonCrypto/CommonHMAC.h>
  18. #import "FirebaseDatabase/Tests/third_party/Base64.h"
  19. @implementation FTestAuthTokenGenerator
  20. + (NSString *)jsonStringForData:(id)data {
  21. NSData *jsonData = [NSJSONSerialization dataWithJSONObject:data options:kNilOptions error:nil];
  22. return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
  23. }
  24. + (NSNumber *)tokenVersion {
  25. return @0;
  26. }
  27. + (NSMutableDictionary *)createOptionsClaims:(NSDictionary *)options {
  28. NSMutableDictionary *claims = [[NSMutableDictionary alloc] init];
  29. if (options) {
  30. NSDictionary *map = @{
  31. @"expires" : @"exp",
  32. @"notBefore" : @"nbf",
  33. @"admin" : @"admin",
  34. @"debug" : @"debug",
  35. @"simulate" : @"simulate"
  36. };
  37. for (NSString *claim in map) {
  38. if (options[claim] != nil) {
  39. NSString *claimName = [map objectForKey:claim];
  40. id val = [options objectForKey:claim];
  41. [claims setObject:val forKey:claimName];
  42. }
  43. }
  44. }
  45. return claims;
  46. }
  47. + (NSString *)webSafeBase64:(NSString *)encoded {
  48. return [[[encoded stringByReplacingOccurrencesOfString:@"=" withString:@""]
  49. stringByReplacingOccurrencesOfString:@"+"
  50. withString:@"-"] stringByReplacingOccurrencesOfString:@"/"
  51. withString:@"_"];
  52. }
  53. + (NSString *)base64EncodeString:(NSString *)target {
  54. return [self webSafeBase64:[target base64EncodedString]];
  55. }
  56. + (NSString *)tokenWithClaims:(NSDictionary *)claims andSecret:(NSString *)secret {
  57. NSDictionary *headerData = @{@"typ" : @"JWT", @"alg" : @"HS256"};
  58. NSString *encodedHeader = [self base64EncodeString:[self jsonStringForData:headerData]];
  59. NSString *encodedClaims = [self base64EncodeString:[self jsonStringForData:claims]];
  60. NSString *secureBits = [NSString stringWithFormat:@"%@.%@", encodedHeader, encodedClaims];
  61. const char *cKey = [secret cStringUsingEncoding:NSUTF8StringEncoding];
  62. const char *cData = [secureBits cStringUsingEncoding:NSUTF8StringEncoding];
  63. unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
  64. CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
  65. NSData *hmac = [NSData dataWithBytesNoCopy:cHMAC length:CC_SHA256_DIGEST_LENGTH freeWhenDone:NO];
  66. NSString *encodedHmac = [self webSafeBase64:[hmac base64EncodedString]];
  67. return [NSString stringWithFormat:@"%@.%@.%@", encodedHeader, encodedClaims, encodedHmac];
  68. }
  69. + (NSString *)tokenWithSecret:(NSString *)secret
  70. authData:(NSDictionary *)data
  71. andOptions:(NSDictionary *)options {
  72. NSMutableDictionary *claims = [self createOptionsClaims:options];
  73. [claims setObject:[self tokenVersion] forKey:@"v"];
  74. NSNumber *now = [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]];
  75. [claims setObject:now forKey:@"iat"];
  76. [claims setObject:data forKey:@"d"];
  77. return [self tokenWithClaims:claims andSecret:secret];
  78. }
  79. @end