Parse JWT Header
This commit is contained in:
@@ -7,18 +7,15 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
821E160721D7ED3F00E2D71A /* TokenDeserializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821E160621D7ED3F00E2D71A /* TokenDeserializer.swift */; };
|
||||
82CAF46A21D7D41800FED241 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CAF46921D7D41800FED241 /* AppDelegate.swift */; };
|
||||
82CAF46C21D7D41C00FED241 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 82CAF46B21D7D41C00FED241 /* Assets.xcassets */; };
|
||||
82CAF46F21D7D41C00FED241 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 82CAF46D21D7D41C00FED241 /* MainMenu.xib */; };
|
||||
82CAF47B21D7D41C00FED241 /* JotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CAF47A21D7D41C00FED241 /* JotTests.swift */; };
|
||||
82CAF48821D7D56D00FED241 /* JWT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CAF48721D7D56D00FED241 /* JWT.swift */; };
|
||||
82CAF48921D7D57700FED241 /* JWT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CAF48721D7D56D00FED241 /* JWT.swift */; };
|
||||
82CAF48B21D7D5B700FED241 /* Payload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CAF48A21D7D5B700FED241 /* Payload.swift */; };
|
||||
82CAF48D21D7D60100FED241 /* Header.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CAF48C21D7D60000FED241 /* Header.swift */; };
|
||||
82CAF48F21D7D81800FED241 /* Signature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CAF48E21D7D81800FED241 /* Signature.swift */; };
|
||||
82CAF49021D7DC5100FED241 /* Payload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CAF48A21D7D5B700FED241 /* Payload.swift */; };
|
||||
82CAF49121D7DC5300FED241 /* Header.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CAF48C21D7D60000FED241 /* Header.swift */; };
|
||||
82CAF49221D7DC5600FED241 /* Signature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CAF48E21D7D81800FED241 /* Signature.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -32,6 +29,7 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
821E160621D7ED3F00E2D71A /* TokenDeserializer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenDeserializer.swift; sourceTree = "<group>"; };
|
||||
82CAF46621D7D41800FED241 /* Jot.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Jot.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
82CAF46921D7D41800FED241 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
82CAF46B21D7D41C00FED241 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
@@ -113,6 +111,7 @@
|
||||
82CAF48A21D7D5B700FED241 /* Payload.swift */,
|
||||
82CAF48C21D7D60000FED241 /* Header.swift */,
|
||||
82CAF48E21D7D81800FED241 /* Signature.swift */,
|
||||
821E160621D7ED3F00E2D71A /* TokenDeserializer.swift */,
|
||||
);
|
||||
path = Token;
|
||||
sourceTree = "<group>";
|
||||
@@ -224,6 +223,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
821E160721D7ED3F00E2D71A /* TokenDeserializer.swift in Sources */,
|
||||
82CAF48D21D7D60100FED241 /* Header.swift in Sources */,
|
||||
82CAF48B21D7D5B700FED241 /* Payload.swift in Sources */,
|
||||
82CAF46A21D7D41800FED241 /* AppDelegate.swift in Sources */,
|
||||
@@ -236,11 +236,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
82CAF49121D7DC5300FED241 /* Header.swift in Sources */,
|
||||
82CAF49021D7DC5100FED241 /* Payload.swift in Sources */,
|
||||
82CAF47B21D7D41C00FED241 /* JotTests.swift in Sources */,
|
||||
82CAF49221D7DC5600FED241 /* Signature.swift in Sources */,
|
||||
82CAF48921D7D57700FED241 /* JWT.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@@ -23,7 +23,9 @@ enum JwtType: String, Codable {
|
||||
}
|
||||
|
||||
enum SigningAlgorithm: String, Codable {
|
||||
case rsa = "RSA"
|
||||
case hmac = "HMAC"
|
||||
case ecdsa = "ECDSA"
|
||||
case rsa256 = "RS256"
|
||||
case rsa384 = "RS384"
|
||||
case rsa512 = "RS512"
|
||||
case hmac256 = "HM256"
|
||||
case ecdsa256 = "ES256"
|
||||
}
|
||||
|
@@ -9,19 +9,13 @@
|
||||
import Foundation
|
||||
|
||||
class JWT {
|
||||
private let header: Header
|
||||
private let payload: Payload
|
||||
private let signature: Signature
|
||||
let header: Header
|
||||
let payload: Payload
|
||||
let signature: Signature
|
||||
|
||||
init(header: Header, payload: Payload, signature: Signature) {
|
||||
self.header = header
|
||||
self.payload = payload
|
||||
self.signature = signature
|
||||
}
|
||||
|
||||
init?(token: String) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
62
Jot/Token/TokenDeserializer.swift
Normal file
62
Jot/Token/TokenDeserializer.swift
Normal file
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// TokenDeserializer.swift
|
||||
// Jot
|
||||
//
|
||||
// Created by James Griffin-Allwood on 2018-12-29.
|
||||
// Copyright © 2018 James Griffin-Allwood. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import os.log
|
||||
|
||||
extension JWT {
|
||||
convenience init?(token: String) {
|
||||
let decoder = JSONDecoder()
|
||||
let jwtParts = token.split(separator: ".")
|
||||
guard jwtParts.count == 3 else {
|
||||
os_log("Invalid JWT format. Requires 3 parts", log: OSLog.default, type: .error)
|
||||
return nil
|
||||
}
|
||||
|
||||
let base64Header = String(jwtParts[0])
|
||||
guard let headerData = Data(base64Encoded: base64Header.base64Pad()) else {
|
||||
os_log("Header must be Base64 Encoded", log: OSLog.default, type: .error)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
let base64Payload = String(jwtParts[1])
|
||||
guard let payloadData = Data(base64Encoded: base64Payload.base64Pad()) else {
|
||||
os_log("Payload must be Base64 Encoded", log: OSLog.default, type: .error)
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: Base64 Decoding the signature fails. Leave alone until adding Token Validation
|
||||
// let base64Signature = String(jwtParts[2])
|
||||
// guard let signatureData = Data(base64Encoded: base64Signature.base64Pad()) else {
|
||||
// os_log("Signature must be Base64 Encoded", log: OSLog.default, type: .error)
|
||||
// return nil
|
||||
// }
|
||||
|
||||
do {
|
||||
let header = try decoder.decode(Header.self, from: headerData)
|
||||
let payload = try decoder.decode(Payload.self, from: payloadData)
|
||||
let signature = Signature()
|
||||
self.init(header: header, payload: payload, signature: signature)
|
||||
} catch {
|
||||
os_log("Unable to deserialize JWT: %@", log: OSLog.default, type: .error, error.localizedDescription)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
func base64Pad() -> String {
|
||||
var paddedString = self
|
||||
if self.count % 4 != 0 {
|
||||
let charactersToAdd = 4 - self.count % 4
|
||||
paddedString.append(contentsOf: repeatElement("=", count: charactersToAdd))
|
||||
}
|
||||
return paddedString
|
||||
}
|
||||
}
|
@@ -10,13 +10,15 @@ import XCTest
|
||||
@testable import Jot
|
||||
|
||||
class JotTests: XCTestCase {
|
||||
var jwt: JWT?
|
||||
|
||||
override func setUp() {
|
||||
self.jwt = JWT(token: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJqZ3JpZmZpbiIsIm5hbWUiOiJKYW1lcyBHcmlmZmluIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.DXfNW7Gzvie7LIl5-HSG9clm3sjeglYG2uNmsPvcNerBQbzLI06vys4YqqCMtrWKEFij_y2hKGP9YFdHSRMdtyVcGEXmYP6H6E62uGhASmGFzEHeSa6B1X1-v8lRt_YpIGEXhkUnxfhdcQ90HJlNfajv0ndnRFk8YJxRkmr99OI")
|
||||
}
|
||||
|
||||
func testJWTInit() {
|
||||
XCTAssertNotNil(self.jwt)
|
||||
guard let jwt = JWT(token: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJqZ3JpZmZpbiIsIm5hbWUiOiJKYW1lcyBHcmlmZmluIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.DXfNW7Gzvie7LIl5-HSG9clm3sjeglYG2uNmsPvcNerBQbzLI06vys4YqqCMtrWKEFij_y2hKGP9YFdHSRMdtyVcGEXmYP6H6E62uGhASmGFzEHeSa6B1X1-v8lRt_YpIGEXhkUnxfhdcQ90HJlNfajv0ndnRFk8YJxRkmr99OI") else {
|
||||
XCTFail()
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertEqual(jwt.header.alg, SigningAlgorithm.rsa256)
|
||||
XCTAssertEqual(jwt.header.typ, JwtType.jwt)
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user