Search code examples
swifthttp-method

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


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;

Solution

  • 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}")