Need help with oAuth2 ticktick call

This is not an Obsidian issue. This is a “unfamiliar with JS developer” issue.

Trying to write a plugin for ticktick.

Can’t get past the oAuth 2 call.
I’ve gotten the authorization token ok. But I’m getting a 401 when I call the token API. What am I missing?

Code:

	async authenticate(args: TickTickArgs): Promise<Error> {
		console.log("Authenticating.")
		let requestURL = `https://ticktick.com/oauth/token`;
		const data = `client_id=${args.client_id}&client_secret=${args.client_secret}&code=${args.token}&grant_type=authorization_code&scope=tasks=write%20tasks=read&redirect_uri=http=//localhost/callback`
		console.log(data)
		console.log(requestURL);
		let auth = btoa(`${args.auth.username}:${args.auth.password}`);
		console.log(auth);
		let resp = JSON.parse(await request({
			method: "POST",
			url: requestURL,
			headers: {
				'Content-Type': 'application/x-www-form-urlencoded',
				'Origin': "https://ticktick.com",
				'Authorization': `Basic ${auth}`,
				'accept': 'application/json'		
			},
			body: data
		}));
		console.log(resp);
		if (resp.error != null) {
			return new Error(resp.error);
		}

		await args.tokenCacher(resp.token);
		this.token = resp.token;

		await this.getSortOrder();

		return null

	}

1 Like

Apparently can’t edit posts?

Anyway, cleaner version of the (still not working) code:

	async authenticate(args: TickTickArgs): Promise<Error> {
		console.log("Authenticating.")
		let requestURL = `https://ticktick.com/oauth/token`;
		console.log(requestURL);
		
		let auth = btoa(`${args.auth.username}:${args.auth.password}`);

		let resp = await request({
			method: "POST",
			url: requestURL,
			contentType: 'application/x-www-form-urlencoded',
			headers: {
				'Origin': "https://ticktick.com",
				'Authorization': `Basic ${auth}`,
			},
			body: new URLSearchParams({
				client_id:args.client_id,
				client_secret:args.client_secret,
				code:args.token,
				grant_type: 'authorization_code',
				scope: 'tasks:read tasks:write',
				redirect_uri: 'http://localhost/callback'
			}).toString(),
		});
		console.log(resp);
		const resp2 = JSON.parse(resp);
		if (resp2.error != null) {
			return new Error(resp2.error);
		}
}

No idea, but here’s what ChatGPT says…

When you’re encountering a 401 Unauthorized error in an OAuth 2.0 flow, there are a variety of places where things could go awry. Here are some points to consider for debugging your issue:

Authorization Header

Your Authorization header uses basic authentication with username and password encoded in Base64. Ensure that the args.auth.username and args.auth.password are correct. Also, make sure that the Basic Auth is actually required at this stage by TickTick’s OAuth service; sometimes only client_id and client_secret in the request body are needed.

Token

Double-check if args.token contains the correct value for the authorization code. Make sure it’s not expired or used before.

Scope

Is the scope (tasks:read tasks:write) you’re requesting correct and allowed by the service? A mismatch could result in a 401.

Redirect URI

Make sure the redirect_uri value (‘http://localhost/callback’) exactly matches the one you’ve set up in your application on the TickTick developer console. Even a trailing slash can cause problems.

URL and Content Type

Your content type is ‘application/x-www-form-urlencoded’, which should match the server’s expectations for this endpoint. Validate this against TickTick’s API documentation.

Debugging Tips

  • Inspect the server’s response; it might contain clues.
  • Compare each part of your request against TickTick’s OAuth documentation.
  • Check if your network environment (like firewalls or proxy servers) is affecting the request.

Code Suggestions

Since you’re using JavaScript, you can add a .catch block to handle any errors that occur during the await request(). It might give you more insights into what went wrong.

Here’s a minor modification with the addition of .catch:

let resp = await request({
  // ... existing code
})
.catch(error => {
  console.log("Request failed", error);
});
1 Like

Thanks! Will double check all that. I’m pretty sure I do have it all right, but I’m at the point where I’m focused on the knots in the trees, and possibly missing whole trees and forests. Will come back to it later.

Much appreciated.