Swift API token retrieval: httpMethod set to POST, but keeps throwing a GET error

52 Views Asked by At

I'm trying to get a token back via the Nordigen API (https://ob.nordigen.com/api/v2/token/new/). However, despite setting the httpMethod = "POST", I keep getting a 405 back stating :

"Method "GET" not allowed".

Very new at Swift, so it must be something basic I'm forgetting.

import Foundation

let apiUrl = URL(string: "https://ob.nordigen.com/api/v2/token/new")!

let clientId = "your_client_id"
let clientSecret = "your_client_secret"
let requestBody: [String: Any] = [
    "client_id": clientId,
    "client_secret": clientSecret
]

let requestData = try! JSONSerialization.data(withJSONObject: requestBody)

var request = URLRequest(url: apiUrl)
request.httpMethod = "POST"
request.httpBody = requestData
request.setValue("application/json", forHTTPHeaderField: "Content-Type")

let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
    if let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
        print(json)
        if let accessToken = json["access"] as? String {
            print("Access Token: \(accessToken)")
        }
    }
}

task.resume()

Copy/pasting the above literally, even without actually having a Nordigen client id/secret, should throw a 401 "Authentication failed" error, stating:

"No active account found with the given credentials".

I tried the following code in JavaScript to ensure the API itself is working and there it works...

    var userid = "user id;
    var userkey = "user key;

    var raw = JSON.stringify({"secret_id":userid,"secret_key":userkey});
    var myHeaders = {"accept": "application/json",
                    "Content-Type": "application/json"}

    var requestOptions = {
      'method': 'POST',
      'headers': myHeaders,
      'payload': raw
    };

    var response = UrlFetchApp.fetch("https://ob.nordigen.com/api/v2/token/new/", requestOptions);
    var json = response.getContentText();
    token = JSON.parse(json).access;
1

There are 1 best solutions below

1
mjr On BEST ANSWER

Your code looks fine with the exception of one minor issue. The endpoint you're hitting has been updated per the latest docs -> https://bankaccountdata.gocardless.com/user-secrets/

I believe the correct endpoint is now:

https://bankaccountdata.gocardless.com/api/v2/token/new/

I've tested the below code and it works with my key and id. This is the exact code tested which includes a couple of minor error handling tweaks off the back of yours:

    let secretId = Constants.secretId
    let secretKey = Constants.secretKey
    
    let apiUrl = URL(string: "https://bankaccountdata.gocardless.com/api/v2/token/new/")!

    let requestBody: [String: Any] = [
        "secret_id": secretId,
        "secret_key": secretKey
    ]

    do {
        let requestData = try JSONSerialization.data(withJSONObject: requestBody)
        
        var request = URLRequest(url: apiUrl)
        request.httpMethod = "POST"
        request.httpBody = requestData
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        let task = URLSession.shared.dataTask(with: request) { (data, response, error) in

            if let error = error {
                print("Error: \(error.localizedDescription)")
                return
            }
            
            if let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
                
                if let accessToken = json["access"] as? String {
                    print("Access Token: \(accessToken)")
                }
            }
        }
        
        task.resume()
    } catch {
        print("Error creating JSON data: \(error.localizedDescription)")
    }

Response in swift console:

Optional("
{\"access\":\"eyJ0exxxxxx\",
\"access_expires\":86400,
\"refresh\":\"eyJ0eXAiOixxxxx\",
\"refresh_expires\":2592000}")