Custom App that need to refresh Bearer token before each module call

Hi Community! Maybe someone can help me out.

I need to connect to a custom app (personio) and they have a somehow strange behaviour for their API (see this /auth). It is no OAuth1/2 nor JWT. It is something in between or more like a normal API call.

  1. First call goes to /auth Endpoint with client-id/secret. The Bearer token get’s returned in body. Ok …

  2. Second call goes to all the other API Endpoints with the Bearer-token in header. The response header contains the next valid Bearer token, because the first one is now blacklisted.

So ie. for Search-Modules with paging the first page ie. works, the second load will fail with 401 error.

Question 1:
Is it possible in “Make.com”, that a single module will call/refresh the token that is persisted in the Connection? As I understand this is refreshed by creating the connection and then hold for several minutes/hours? So that on each Module-Call the Connection call is also executed.

Question 2:
Sure, what I did (and that works) is to leave the Connection part from app empty an just add a new Modules call it “Authentication” that returns a token that could be used in a second module. Each time you call a Module, you need to provide a new an fresh token. That is ugly and paging is still not supported.

Maybe I missed something in the documentation but I never had a problem like this.

Thanks!

Hi @Frank_Szilinski,

It seems weird, I will try to review it more and see how best this can be done, But, Maybe the easiest solution will be to discard the token that you are getting from the Personio response after an API call and instead trigger a new connection every time and API needs to be triggered.

So, in Connection what you can do is Use, Oauth 2 as a connection and then just basically set the token with a condition always set to true which will ensure that a new token is always triggered.

{
	"token": {
		"condition": "{{true}}",
		"url": "https://personiosomethingendpoint/auth",
		.........
	}
}
2 Likes

Hi @Runcorn!

I tried it with your suggested solution to set the condition to “true” and using a faked OAuth Connection. Thanks for the great idea!

Conenction looks like that:

{
	"token": {
		"condition": "{{true}}",
		"url": "https://api.personio.de/v1/auth",
		"headers": {
			"accept": "application/json",
			"content-typ": "application/json",
			"X-Personio-Partner-ID": "xxx"
		},
		"body": {
			"client_id": "{{parameters.clientId}}",
			"client_secret": "{{parameters.clientSecret}}"
		},
		"type": "urlencoded",
		"method": "POST",
		"response": {
			"data": {
				"token": "{{body.data.token}}"
			}
		},
		"log": {
			"sanitize": ["request.body.client_secret", "response.body.token"]
		}
	}
}

I wrote one module to test if I can page all employees from the source. It looks like that (see API here):

{
	"url": "/company/employees",
	"method": "GET",

	"headers": {
		"accept": "application/json",
		"content-typ": "application/json",
        "authorization": "Bearer {{ifempty(connection.token, headers.authorization}}",
		"X-Personio-Partner-ID": "xxx"
    },	
	"qs": {
		"limit": "{{parameters.limit}}",
		"offset": "{{parameters.offset}}",
		"email": "{{lower(parameters.email)}}",
		"updated_since": "{{parameters.updated_since}}"
	},
	"response": {
		"output": "{{item}}",
		"iterate": "{{body.data}}",
        "error": {
			"type": "{{body.error.code}}",
            "message": "[{{statusCode}}] {{body.error.message}} (token={{connection.token}}) (error code: {{body.error.code}}')"
        },	
		"valid": "{{if(body.error.code, false, true)}}"
	},
	"pagination": {
		"qs": {
			"Page": "{{pagination.page}}"
		},
		"condition": "{{body.metadata.total_pages >= pagination.page}}"
	}
}

This seems to work.

I think the only problem is, that they have a throtteling on the /auth endpoint with 60calls/min. That could be a limitation why I think it would somehow be better, if we can pass the header-data (headers.authorization) from first call to the second.

Is there an alternative way even if that works now?

There was an error in the “List Employees” module with pagination. This is correct (docu here):

{
	"url": "/company/employees",
	"method": "GET",

	"headers": {
		"accept": "application/json",
		"content-typ": "application/json",
        "authorization": "Bearer {{ifempty(connection.token, headers.authorization}}",
		"X-Personio-Partner-ID": "esentri"
    },	
	"qs": {
		"limit": "{{parameters.limit}}",
		"offset": "{{parameters.offset}}",
		"email": "{{lower(parameters.email)}}",
		"updated_since": "{{parameters.updated_since}}"
	},
	"response": {
		"output": "{{item}}",
		"iterate": "{{body.data}}",
        "error": {
			"type": "{{body.error.code}}",
            "message": "[{{statusCode}}] {{body.error.message}} (token={{connection.token}}) (error code: {{body.error.code}}')"
        },	
		"valid": "{{if(body.error.code, false, true)}}"
	},
	"pagination": {
		"qs": {
			"offset": "{{(pagination.page-1)*parameters.limit}}"
		}
	}
}

What’s the error you are getting?

For the initial one, What you can do is remove the true condition, and then for things like Pagination,

You can override the,

`“authorization”: “Bearer {{ifempty(connection.token, headers.authorization}}”,

within the pagination block as,

"pagination": {
                "headers" : {
              `"authorization": "Bearer {{headers.authorization""",

               },
		"qs": {
			"offset": "{{(pagination.page-1)*parameters.limit}}"
		}
	}

Although this should work, the problem might still persist depending on how your token is handled.

1 Like