Swift-JWT decoding issue - swift

I am using the Swift-JWT Cocoapod file, when I try to encode a particular claim struct, it gives me a cryptogram, when I check in this cryptogram on the https://jwt.io/ website, it is decoding successfully but the order of the claim struct object is changing. I don't know what to do right now?
any suggestions much appreciate
Note:- I need when we are going encode of the claim struct, that same struct need to decode with the same order.
for example, This is my claim struct with using private key, I am encoding the data
ClaimsRequest(
deviceId: "1D9B98D1-63FE-466B-99CB-A2CBDEB1612F",
amount: "32.00",
currency: "MUR",
debtorAccount: "1234567890",
creditorAccount: "255252522",
endToEndId: "CMCLMUM020220202000019",
consentId: "88379")
privateKey:
Printing description of privateKey:
"MIIEujANBgkqhkiG9w0BAQEFAAOCBKcAMIIEogIBAAKCAQEAotx6XajXdQFkn4LmqLhYgU0PVksLUc5X0eHpPicGoSsL7LtEY3Cp8x8iCZxdo0dxB+AUfl+deklS7alRkjgc5bp8Z2NCe5fNX4zeS2XVsk7W5wYQmUc2xnrX2yyTq81rnQ32SXppWEU/iGsUbWRTBaJYFxjIGM+qjcGnIHK9dvXkiN075uXyT8jVJOAbPUTSrtIcgpplxlhBprtyzl8A0FtRXRJOpv5MgJDn3nudIpTimFI6kgOjzVTLu1RhBIeDW5CwdgMPIQ1E3HyZ34wsqviY9q5BQ+2Q+d8NiL/NtxNEDoMm1+8L/BvPIZDJH5DXEXJOpkeEVFoC1Mo0xPAz9wIDAQABAoIBACwGBE/YCbHXuA8ET/yQpGADaB9v9rXc3NFfy3BhFUIwxC7waiqlNFODeWx2p7sw3yV9VZzZlNSPCIs051dqsqkI0YMTClAldz8acaaY9vyVojLd6VO9s9lQMJRPBvX8d9gDA63WGK7jPSrPozx0z5poyX4o1UIbtKNQEzDKw1tp6yTTm91ad4K+yH/yQuuLVA44VP1kfMNtmMIYqHyn5eeWRQiOTPvslByEqSd84YdQZyz2JFTDDrFpI13TDJpoMf2p4jsIYYliv2bvuG2dB8bFtNR0fVUSWVE1GBCag7k29kH8ieRodZR8Sa79J3teoEvC4+Czn9YxpN/3D07bSuECgYEA1cAzWj8b2adlVqsk5ePtzsVY8e/Kk2qDGVMu/QehMoi3gdXL8+0A/58d3m4KAjW4SX9qw+RQsq3+EDjx+m5g4wE8uLTy4EsrBNaZ1si0V63WiNUPSGNk5jzGpgT9qsbSFm1KhhH3CDcAm2cRy6NkG0fcQ3VX6aK0KnFMUg+q2VcCgYEAww1Dp64ZfXDJHynB/Ne219gZGk5aMP8/4UFirMVXZLJTiSRXTe1f/YYPSB+3AQmprJfXT4/jk3ubxCxJ7f1PP6EwPXrH76G/wm/sNR8aK04i4p3kR8qCLEmks5ZN+G29uoJ3S35loydk4iLjwxNGrzlo2O45gRNbInJN+HjQtmECgYBYN8L59CHiapwAcRIBb1iuhfR3pafNv5/ry9EQzR1SZeqWw04xlhdbaKhDLNckolc0vkmqH4jOtdCtkVMNMJD8H36YHNZAi8VtccR8SMllhnGMd6KfFaaG/35c9qJa4UPDzcd8Hd3+nfS6LofBq+Wc/MODc+KconIJMkl1dNHmcQKBgHwsY5fKVFvxg3idYuwOgE6lOkXu/6gVt5s1vxXyhBKNHHVAd3wa1HNX9z6ZQi4c8rH38JCsL9tiY+XdtCsYim0dttJM6h/6P1QPYLbo2AYdtkPC9ONnXrvHHl1eIME5TAICsOOU0iuuFqGISKuWB/fheogwENfFdM1XK6A1ednBAoGAGIqs9UdlLVtOPqT1EIxceyH3JpncIsFeh7jcIYu6aGI1KqaNz094Ex88p9q5dylqE6iblq+n4EIyvB6MvCTGH2iYBU5M7GAlSWqGbNloFFMB7nSlzPOfKu6bwWSNn7S+ywx9gXx3IMpB/zxpFupaccuNn1A0Bk2E8kBYqooPNRw="
var myJWT = JWT(claims: myClaims)
do {
if let privateKeyData = Data(base64Encoded: privateKey) {
let jwtSigner = JWTSigner.rs512(privateKey: privateKeyData)
let signedJWT = try myJWT.sign(using: jwtSigner)
return signedJWT
}
}
it is given cryptogram of the data
Printing description of cryptogram:
▿ Optional
some : "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJhbW91bnQiOiIzMi4wMCIsImRldmljZUlkIjoiMUQ5Qjk4RDEtNjNGRS00NjZCLTk5Q0ItQTJDQkRFQjE2MTJGIiwiY3JlZGl0b3JBY2NvdW50IjoiMjU1MjUyNTIyIiwiZW5kVG9FbmRJZCI6IkNNQ0xNVU0wMjAyMjAyMDIwMDAwMTkiLCJkZWJ0b3JBY2NvdW50IjoiMTIzNDU2Nzg5MCIsImN1cnJlbmN5IjoiTVVSIiwiY29uc2VudElkIjoiODgzNzkifQ.gjI_il7eu_topH2-i_UY_vFrD3rGpMe5a8R-mbO48MbKYaVcIJuNO4QxaqBR-nltBn5fPnZfWqxta6jqFJ4-W1CDIIVTDNI6vGZn8UTgn8TkZ21VA1wNb0Os067dGrDHtzlvJwrwOhLD2cND5F_YbN7v_cYMJEkTDKgTyi6w4HW3jqZPzMfEMfjQ36jlM8KlCf1_XeZ1V-OzNOmBhc6ToErHYJbM61fmV2DjVShGVqZ2dFu1Myw1FpaVvbp8YTA6_POq1kk3p8Ml6s6o0SQ3-c4cZ6f08z16fGGO7K-Tn7fDenZgX8oRQ0YvV3LeGzbbYgGFaqES_7KK1txLPOqTww"
So, when I paste this cryptogram in JWT.io it gives decoding Object, here you can see order changing of claim struct.
{
"amount": "32.00",
"deviceId": "1D9B98D1-63FE-466B-99CB-A2CBDEB1612F",
"creditorAccount": "255252522",
"endToEndId": "CMCLMUM020220202000019",
"debtorAccount": "1234567890",
"currency": "MUR",
"consentId": "88379"
}

Related

ObjectMapper and arrays with unique keys

Im running into an issue with ObjectMapper and the way a json response is coming back from a server.
Is there a way to have ObjectMapper parse this response and create an array of rooms?
Currently I cannot straight map the json as the keys are unique, and will change every request, as well I cannot use the ObjectMapper way of accessing nested objects with dot notation, rooms.0.key as I am unsure how many objects there are, as well as the key that will show up.
Is there a simple way of parsing this reponse.
"rooms": {
"165476": {
"id": "165476",
"area": {
"square_feet": 334,
"square_meters": 31
},
"165477": {
"id": "165477",
"area": {
"square_feet": 334,
"square_meters": 31
},
Use Codable to parse the above JSON response.
Models:
struct Rooms: Codable {
let rooms: [String:Room]
}
struct Room: Codable {
let id: String
let area: Area
}
struct Area: Codable {
let squareFeet: Int
let squareMeters: Int
}
Parse the JSON data like so,
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let response = try decoder.decode(Rooms.self, from: data)
print(response.rooms.first?.key) //for the above json it will print "165476"
} catch {
print(error)
}

Swift 4 Json Decoding, Which is the best/latest method, Using Codable or Decodable?

In Swift 4.1 we can decode JSON like this:
struct Person: Decodable {
let id: Int
let name: String
let imageUrl: String
}
let people = [Person]()
func parseJSON(data: Data) {
do {
let decoder = JSONDecoder()
decoder.keyDecodingStratergy = .convertFromSnakeCase
self.people = try decoder.decode([Person].self, from: data)
} catch let error {
print(error as? Any)
}
}
Q1. What is the difference if I use Codable instead of Decodable? Which is better?
Q2. How to use decodeIfPresent here?
Q3. How to decode if there is no key present in the JSON?
The best way to encode and decode JSON in Swift4
Here is the JSON representation of a simple object User, let’s see how to deserialise those data into an object.
{
"id": 13,
"firstname" : "John",
"lastname" : "Doe",
"email" : "john.doe#lost.com"
}
Decoding JSON into object
I use a struct type to represent my object and include the protocol Decodable to allow deserialisation.
struct User : Decodable {
let id : Int
let firstname : String
let lastname : String
let email : String
}
Now we’re ready to decode it using JSONDecoder.
// assuming our data comes from server side
let jsonString = "{ \"id\": 13, \"firstname\" : \"John\", \"lastname\" : \"Doe\", \"email\" : \"john.doe#lost.com\" }"
let jsonData = jsonString.data(using: .utf8)!
do {
let jsonDecoder = JSONDecoder()
let user = try jsonDecoder.decode(User.self, from: jsonData)
print("Hello \(user.firstname) \(user.lastname)")
} catch {
print("Unexpected error: \(error).")
}
Pretty easy right? Let’s see how to serialise it now.
Encoding object into JSON
First, we need update our struct to allow encoding. To do so, we just need to include protocol Encodable.
struct User : Encodable, Decodable {
...
}
Our object is ready to be serialised back to JSON. We follow the same process as before, using JSONEncoder this time. In that case, I’ll also convert the data into a String to be sure it’s working
// assuming we have an object to serialise
That’s still pretty easy! So what is Codable all about?
Well, Codable, is just alias of Encodable and Decodable protocols as you can see in it’s definition
public typealias Codable = Decodable & Encodable
If you don’t want your JSON keys to drive your naming, you can still customise them using CodingKeys. Described as an enum, it will automatically be picked up while encoding / decoding
struct User : Codable {
var id : Int
var firstname : String
var lastname : String
var email : String?
// keys
private enum CodingKeys: String, CodingKey {
case id = "user_id"
case firstname = "first_name"
case lastname = "family_name"
case email = "email_address"
}
}
To go further
https://medium.com/#phillfarrugia/encoding-and-decoding-json-with-swift-4-3832bf21c9a8
https://benoitpasquier.com/encoding-decoding-json-swift4/
Answer of Question 3: https://www.calhoun.io/how-to-determine-if-a-json-key-has-been-set-to-null-or-not-provided/
Please if possible try to post separated questions, it is easier to answer and to read after.
For your first question: Codable is a protocol extending Encodable and Decodable.
Decodable is to parse from data to your models. For example from JSON data to structs.
Encodable is to make data from your models.
Codable contains both.

How to Hash sha256 in swift 4 with a secret key?

I am currently working on a project (in swift 3/4) where I need to hash a HTTP request that is formatted as so:
{"request": {"method": "getMyPeople",
"params": {"api_key": 00de5089d590e413807343166da22a45,
"user_id": 8 }, "id": "1"}}
I am trying to hash in SHA-256 with a secret key, something that looks like this:
6b107c7ebebf056e1c45924d0546d35e
What I need:
I need to be able to hash with sha256 with a secret key.
I need that hashed request to be a string in hex form in order for me to make a request to the database
What I have:
Set up my header bridge file to use objective-c code
Looked into many solutions and none of them worked for me
Solutions I have tried:
My most recent attempt is Zaph's post here (https://stackoverflow.com/a/39249920/8093921).
Where my issue occurs:
My issue seems to occurring when I try to convert the form of
hashSHA256: <aabc766b 6b357564 e41f4f91 2d494bcc bfa16924 b574abbd ba9e3e9d a0c8920a>
as seen in Zaph's post, they leave it in this form where I need it in form of a string in hex.
If anyone need any more clarification please let me know.
Thank you in advance for the help!
I admit that it can be confusing to get everything together but the final solution is quite simple:
extension String {
func hmac(key: String) -> String {
var digest = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), key, key.count, self, self.count, &digest)
let data = Data(bytes: digest)
return data.map { String(format: "%02hhx", $0) }.joined()
}
}
Example:
let result = "test".hmac(key: "test")
Result:
88cd2108b5347d973cf39cdf9053d7dd42704876d8c9a9bd8e2d168259d3ddf7

Decodable returning object

I have a decodable class:
struct AuthenticationResponse : Decodable {
var status: String
var error: Error
var access_token: String? = ""
var expires_in: Double? = 0
var token_type: String? = ""
var scope: String? = ""
var refresh_token: String? = "
}
struct Error : Decodable {
var desc: String
var code: String
}
In the Error class I have:
And to decode to this class, I have:
URLSession.shared.dataTask(with: request) { (data:Data?, response:URLResponse?, error:Error?) in
if let jsonData = data{
let decoder = JSONDecoder()
print("hey")
print("response: \(String(data:jsonData, encoding:.utf8))")
completion(try! decoder.decode(AuthenticationResponse.self, from: jsonData))
}
}.resume()
As some of the responses I receive are (Success response):
{
“status”: “SUCCESS” “error”: null, "access_token":
"MWVmOWQxMDYwMjQyNDQ4NzQyNTdkZjQ3NmI4YmVjMGZjZGM5N2IyZmNkOTA1 N2M0NDUzODEwYjM5ZWQyNGNkZg",
"expires_in": 3600, "token_type": "bearer", "scope": null,
"refresh_token":
"ZGEwOGZiOWZhMzhhYjBmMzAyOGRmZTA5NjJhMjY2MTk3YzMyMmE1ZDlkNWI2N mJjYmIxMjNkMjE1NWFhNWY0Mg"
}
And then a failed response just contains an error object with desc and code in it.
What i am trying to achieve is a decodable class suitable for both scenarios (When a response is successful and failed) however im not sure how to achieve this. I'm aware i can make 2 separate decodable classes but this would make things messier as i'd have to determine if the response is an error and populate to return different classes.
Does anyone know how i should acheive this>
I will give it a try, but first we need to sort out what I consider a somewhat shoddy question. Since Error is the name of a (famous and widely used) protocol it should be renamed and since you want to be able to leave it empty in your AuthenticationResponse it must obviously be an optional there (bearing the question why it is in the Response at all, but I will leave this aside). This leaves us with the following:
struct AuthError : Decodable {
var desc: String
var code: String
}
struct AuthenticationResponse : Decodable {
var status: String
var error: AuthError?
var access_token: String? = ""
var expires_in: Double? = 0
var token_type: String? = ""
var scope: String? = ""
var refresh_token: String? = ""
}
Then we need some example data for the two relevant cases in question, I used:
let okData = """
{
"status": "SUCCESS",
"error": null,
"access_token":
"MWVmOWQxMDYwMjQyNDQ4NzQyNTdkZjQ3NmI4YmVjMGZjZGM5N2IyZmNkOTA1N2M0NDUzODEwYjM5ZWQyNGNkZg",
"expires_in": 3600,
"token_type": "bearer",
"scope": null,
"refresh_token":
"ZGEwOGZiOWZhMzhhYjBmMzAyOGRmZTA5NjJhMjY2MTk3YzMyMmE1ZDlkNWI2NmJjYmIxMjNkMjE1NWFhNWY0Mg"
}
""".data(using: .utf8)!
let errData = """
{
"desc": "username or password incorrect",
"code": "404"
}
""".data(using: .utf8)!
Now we can define a single enum return type which allows for all our cases:
enum AuthResult {
case ok(response: AuthenticationResponse)
case authError(error: AuthError)
case parseError(description: String)
case fatal
}
which finally allows us to write our parse function for the received authentication data:
func parse(_ jsonData:Data) -> AuthResult {
let decoder = JSONDecoder()
do {
let authRes = try decoder.decode(AuthenticationResponse.self, from: jsonData)
return .ok(response: authRes)
} catch {
do {
let errRes = try decoder.decode(AuthError.self, from: jsonData)
return .authError(error: errRes)
} catch let errDecode {
return .parseError(description: errDecode.localizedDescription)
}
}
}
All this in a Playground will permit usage as in
switch parse(okData) {
case let .ok(response):
print(response)
case let .authError(error):
print(error)
case let .parseError(description):
print("You threw some garbage at me and I was only able to \(description)")
default:
print("don't know what to do here")
}
That is still elegant compared to the mess you would make in most other languages, but the call is still out on wether it would not make more sense to just define AuthenticationResponse as the (regular) return type of the parse function and provide the rest by throwing some enum (conforming to Error) and some suitable payload.
Coming (mainly) from Java I still shun from using exceptions as "somewhat" regular control flow (as in a "regular" login failure), but given Swifts much more reasonable approach to exceptions this might have to be reconsidered.
Anyways, this leaves you with a function to parse either case of your services replies and a decent way to handle them in a "uniform" manner. As you might not be able to modify the behaviour of the service handling your request this might be the only viable option. However, if you are able to modify the service you should strive for a "uniform" reply that would be parseable by a single call to JSONDecoder.decode. You would still have to interpret the optionals (as you should in the above example, since they are still a pain to work with, even given Swifts brilliant compiler support forcing you to "do the right thing"), but it would make your parsing less error prone.

Send base 64 string with alomofire

I trying to send post request with dictionary, one of its value is base64 string. So, I have parameters dict as follows:
let paramsDict : [String : Any] = [ "image" : self.avatarBase64String]
When I send a request, I got following in console:
FAILURE:
responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error
Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character
0." UserInfo={NSDebugDescription=Invalid value around character 0.}))
My base64 string is correct (quite lot of symbols though), but I did check it online and got an image from output.
Why I got such an error?
Please check your network connection.
Then you convert the imageView into Data and then convert into base64
Hope this code will help you:-
let pic = UIImageJPEGRepresentation(cameraView.image, 0.5)
let avatarBase64String = pic.base64EncodedString()
Here is what I have been using in order to make easy Dictionary representation of your parameters in order to make a POST request with Alamofire.
You can use this in your model class:
var dictionaryRepresentation: [String: Any] {
return [
"name" : self.name,
"title" : self.title,
"avatar" : self.avatar,
"age" : self.age,
]
}
You can remove the self if you are in your model class, it is just for a better understanding.
And then when you want to make your POST request, you can call it this way :
Imagine you have a class User, with attribute name, title, avatar and age as previously shown.
And you want to send your object User to your backend.
Here is how you can send your parameters as dictionary represented :
let user = User(name: name, title: title, avatar: avatar; age: age)
CustomService.shared.post(parameters: user.dictionaryRepresentation) { response in
// Handle response here
}
I strongly recommend you to abstract in a shared Service class all the networking methods.