My bank offers to connect to their APIs using OAuth2. I want to create an App Script to autmatically write my transactions to google docs. This is my first time using OAuth and I can't seem to get the access token. Below I have pasted my attempt at receiving an access token, but the site refuses my request. Below my code example are two code examples (one for Node and one for Python) which are provided by the bank. Are there any obvious mistakes that I don't see?
My code:
function get_auth_token() {
var identityServerUrl = "https://auth.sbanken.no/identityserver/connect/token"; // access token endpoint
var clientId = '...'
var secret = '...'
var basicAuth = Utilities.base64Encode(encodeURIComponent(clientId) + ":" + encodeURIComponent(secret)); // create basicAuth header value according to Oauth 2.0 standard
var response = UrlFetchApp.fetch(identityServerUrl, {
headers: {
'Accept': 'application/json',
'customerId' : clientId,
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + basicAuth}
});
}
Node code from the bank:
exports.getAccessToken = () => {
var identityServerUrl = "https://auth.sbanken.no/identityserver/connect/token"; // access token
endpoint
var clientId = credentials.clientid; // application key received from API Beta in the internetbank
var secret = credentials.secret; // password received from API Beta in the internetbank
var basicAuth = btoa(encodeURIComponent(clientId) + ":" + encodeURIComponent(secret)); // create basicAuth header value according to Oauth 2.0 standard
var accessToken;
// request accessToken (the basic auth data is put on the request header prior to sending the request)
let response;
var promise = new Promise(function (resolve, reject) {
request
.post(identityServerUrl)
.send('grant_type=client_credentials')
.set('Authorization', "Basic "+basicAuth)
.set('Accept', 'application/json')
.set('customerId', credentials.userid)
.end(function(err, res){
if (err || !res.ok) {
console.log(err);
reject();
} else {
console.log('yay got ' + JSON.stringify(res.body));
resolve(res.body);
}
});
});
Python code from the bank:
CLIENT_ID = '' # Get from https://secure.sbanken.no/Personal/ApiBeta/Info/
SECRET = '' # Get this from https://secure.sbanken.no/Personal/ApiBeta/Info/
AUTH_URL = 'https://auth.sbanken.no/identityserver/connect/token'
ACCOUNTS_URL = 'https://api.sbanken.no/exec.bank/api/v1/accounts'
CUSTOMER_ID = '' # Your own personnummer
def get_auth_token(auth_url, client_id, secret):
headers = {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
}
body = {'grant_type': 'client_credentials'}
urlencoded_client_id = urllib.quote(client_id)
urlencoded_secret = urllib.quote(secret)
auth_string_to_be_b64encoded = '{}:{}'.format(
urlencoded_client_id, urlencoded_secret)
b64encoded_auth_string = base64.b64encode(auth_string_to_be_b64encoded)
headers['Authorization'] = 'Basic {}'.format(b64encoded_auth_string)
r = requests.post(url=auth_url, headers=headers, data=body)
auth_token = r.json()['access_token']
return auth_token
From the code samples, I'd bet that you need to pass grant_type=client_credentials
as part of the request. There are two ways you can do this:
https://auth.sbanken.no/identityserver/connect/token?grant_type=client_credentials
Include it as the payload of the UrlFetchApp.fetch()
request (this would be the more "correct" approach):
var response = UrlFetchApp.fetch(identityServerUrl, {
headers: {
'Accept': 'application/json',
'customerId' : clientId,
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + basicAuth
},
payload: 'grant_type=client_credential'
});
Unfortunately, I can't verify if that's all you'll need to do to make it work, but it should get you going in the right direction. Also, I'd really recommend you try to configure this through Google's OAuth2 library, although it isn't the most straight-forward to implement.