App development - Connection with Token bearer which is not Oauth

Hi everyone, happy new year !
I am building a custom app for Sinao and I am struggling with the connection part.
Their authentication process is as follow:

  1. Make a POST /login request with Email and Password as query parameters to obtain a Token
  2. Make a GET request /refresh to refresh token

This process is similar to Oauth 2.0 authentication process except that there is no “pre-authorize” nor “authorize” steps.

I therefore tried to build a Connection by selecting Type = Other where I put the following code in the Communication tab:

{
	"token": {
		"url": "https://api.sinao.app/v1/login",
		"method": "POST",
		"body": {
			"email": "{{parameters.email}}",
			"password": "{{parameters.password}}"
		},
		"type": "urlencoded",
		"response": {
			"data": {		
				"expires": "{{addSeconds(now, body.expires_in)}}",
				"accessToken": "{{body.access_token}}"
				},
			"expires": "{{addDays(now, 14)}}"
		},
		"log": {
			"sanitize": ["request.body.email", "request.body.password", "response.body.accessToken"]
		}
	},
	"refresh": {
		"condition": "{{data.expires < addMinutes(now, 5)}}",
		"url": "https://api.sinao.app/v1/refresh",
		"method": "GET",
		"headers": {
			"Authorization": "Bearer {{data.accessToken}}"
		},
		"type": "urlencoded",
		"response": {
			"data": {
				"expires": "{{addSeconds(now, body.expires_in)}}",
				"accessToken": "{{body.access_token}}"
			},
			"expires": "{{addDays(now, 14)}}"
		},
		"log": {
			"sanitize": ["request.headers.Authorization", "response.body.accessToken"]
		}
	},
    "info": {
        "url": "https://api.sinao.app/v1/me",
        "headers": {
            "Authorization": "Bearer {{connection.accessToken}}"
        },
        "response": {
			"uid": "{{body.id}}",
			"metadata": {
				"type": "text",
				"value": "{{body.firstname}} {{body.lastname}}"
			},
			"error": {
                "message": "[{{statusCode}}] {{if(body.message, body.message, body)}}"
            }
        },
        "log": {
            "sanitize": [
                "request.headers.Authorization"
            ]
        }
    }
}

However, I keep getting 401 error when testing the connection with a simple module Get current user. Would anyone know where the problem comes from ?

Thanks.

Hi @GB_Consultant,

do you see if there POST request and/or refresh process get executed in the Integromat/Make Dev-Tool?

Kind regards,
Richard

1 Like

Hi @Richard_Johannes . Thanks for getting back.

I don’t see any Post request or refresh process being executed in the Dev-Tool. I can actually see that my accessToken is empty (I didn’t sanitize it just for testing purposes).

image

Here is the Base of my app:

{
	"baseUrl": "https://api.sinao.app/v1/",
	"headers": {
        "authorization": "Bearer {{connection.accessToken}}"
    },
	"log": {
		"sanitize": []
	}
}

And here is the communication of the module I am testing, which refers to this endpoint:

{
	"url": "/me",
	"method": "GET",
	"response": {
		"output": "{{body}}"
	}
}

This may be the case if the token isn’t expired yet, correct? And 14 Days expiration time is also right?

I don’t really see what’s causing the issue… :confused: Have you tried connection.data.accessToken?

But if my token hasn’t expired, it should use it rather than leaving it empty, no ?
Regarding the 14 days expiration, it is mentioned here in their documentation in French

Something I did not mention, this is what I see when I add a connection to the app in my module before running it. So if this is the moment where I am supposed to see the POST request, it is not working (but why don’t I get an error message instead if the connection failed?)

connection.data.accessToken did not work either

Yes, if the token isn’t expired it should show the token that is still valid! :smiley:

Sadly, I don’t speak French but 14 days is a lot. They mention 24 hours and 14 days in that abstract so my assumption would be that the Bearer Token is valid for 24 hours and needs to be “refreshed” after that. If you haven’t used the accessToken from your Login for 14 days, you need to create a new token and cannot use it to refresh the Bearer Token anymore. (This may be completely wrong!)

I created a custom App with similar logic in a different manner.

I create the connection using the email + password to receive the access token. Then for every Module I am chaining the API request to always start with an API Call to the refresh endpoint. I do think your approach is way better and “more correct” - just pointing it out if this would be a solution for you as well :smiley:

Please keep me updated 110% interested in the solution!

1 Like

Hi @GB_Consultant ,

I suggest registering the connection with the OAuth2 type. According to the documentation, OAuth2.0 connections are described as follows.

OAuth 2.0 connection handles the token exchange automatically.

Src. OAuth 2.0 - Make Apps

I tried your solution using the “Other” type with information from the open-source Dropbox app, and it didn’t work. So I assume that the connection type is not giving you the result that you expect.

You can use an OAuth connection without setting the authorization block. From my experience, it skips the authorization part and executes the token part immediately.
With the extra advantage that the refresh mechanism is also supported with that connection type.

Please give it a try and let us know your result.

Kr.,
Glenn - Callinetic

1 Like

Hi @GB_Consultant,

I wonder if you’ve solved this issue. I’m facing it aswell and can’t find a solution.

kr,
Tim

@Tim_Glimmerveen,

Can you share me how your API document looks like?

1 Like

@Runcorn
Ofcourse the documentation is: Optiply Public API

The connection i’ve made is the following: (haven’t implemented the refresh yet. If I add this it keeps giving an error when I add the connection)

{
    "token": {
        "url": "https://dashboard.optiply.nl/api/auth/oauth/token?grant_type=password",
        "headers": {
            "Content-Type": "application/x-www-form-urlencoded",
            "Authorization": "Basic {{base64(join(parameters.clientId, ':', parameters.clientSecret))}}"
        },
        "body": {
            "username": "{{parameters.username}}",
            "password": "{{parameters.password}}"
        },
        "type": "urlencoded",
        "method": "POST",
        "response": {
            "type": "json",
            "data": {
                "accessToken": "{{body.access_token}}",
                "expires": "{{addSeconds(now, body.expires_in)}}"
            },
            "expires": "{{addSeconds(now, body.expires_in)}}"
        }
    }
}```

Hi @Tim_Glimmerveen,

I changed one of my apps, so the structure based on the API should look like this, I haven’t thoroughly reviewed the API so there might be some data mapping issue which you can review and see if you can fix it.

{
	"token": {
		"condition": "{{if(data.accessToken, data.expires < addMinutes(now, 15), true)}}",
		"url": "https://dashboard.optiply.nl/api/auth/oauth/token?grant_type=password",
		"headers": {
			"Authorization": "Basic {{base64(ifempty(parameters.clientId, common.clientId) + ':' + ifempty(parameters.clientSecret, common.clientSecret))}}"
		},
		"body": {
			"username": "{{parameters.username}}",
			"password": "{{parameters.password}}"
		},
		"method": "POST",
		"type": "urlencoded",
		"response": {
			"valid": {
				"condition": "{{if(body.access_token,true,false)}}",
				"message": "[{{statusCode}}] {{body.Message}}",
				"type": "AccountValidationError"
			},
			"type": "json",
			"data": {
				"accessToken": "{{body.access_token}}",
				"expires": "{{addSeconds(now, body.expires_in)}}",
				"refreshToken": "{{body.refresh_token}}"
			},
			"expires": "{{addSeconds(now, body.expires_in)}}"
		},
		"log": {
			"sanitize": ["request.body.asdasdasd", "response.body.asd"]
		}
	},
	"refresh": {
		"condition": "{{if(data.accessToken, data.expires < addMinutes(now, 15), true)}}",
		"url": "https://dashboard.optiply.nl/api/auth/oauth/token?grant_type=refresh_token",
		"qs": {
			"refresh_token": "{{parameters.siteId}}"
		},
		"body": {
			"username": "{{parameters.username}}",
			"password": "{{parameters.password}}"
		},
		"headers": {
			"Authorization": "Basic {{base64(ifempty(parameters.clientId, common.clientId) + ':' + ifempty(parameters.clientSecret, common.clientSecret))}}"
		},
		"method": "POST",
		"response": {
			"valid": {
				"condition": "{{if(body.access_token,true,false)}}",
				"message": "[{{statusCode}}] {{body.Message}}",
				"type": "AccountValidationError"
			},
			"data": {
				"accessToken": "{{body.access_token}}",
				"expires": "{{addSeconds(now, body.expires_in)}}",
				"refreshToken": "{{body.refresh_token}}"
			}
		},
		"log": {
			"sanitize": ["request.qs.refresh_token", "response.headers.Authorization"]
		}
	},
	"info": {
		"url": "https://api.optiply.com/v1/accounts",
		"method": "GET",
		"headers": {
			"Authorization": "{{connection.accessToken}}",
			"Content-Type": "application/vnd.api+json"
		},
		"response": {
			"valid": {
				"condition": "{{body.data}}",
				"message": "[{{statusCode}}] {{body.msg}}",
				"type": "AccountValidationError"
			},
			"msg": "{{bodydatamsg}}"
		},
		"log": {
			"sanitize": ["request.headers.Authorization"]
		}
	}
}

I think the initial issue with your settings was how the Authorization header was forwarded.

1 Like

This worked thanks alot!!!