Parse Obsidian protocol URL part after hash (#)

Use case or problem

Trying to integrate with OAuth authentication for Imgur plugin. Imgur OAuth puts response params to callback URL after hash character. Example:

obsidian://imgur-oauth#access_token=ACCESS_TOKEN&token_type=Bearer&expires_in=3600

See related docs section: Imgur API

To handle the response from Imgur I register handler like this:

this.registerObsidianProtocolHandler("imgur-oauth", (params) =>{console.log(params)})

The problem is that neither of access_token, token_type or expires_in is available in handler’s params. Only if Imgur API put params after ? instead of # I would get them, but the data after hash is completely ignored by Obsidian with the current Obsidian implementation (see workaround section for details).

The # used in response from Imgur OAuth API is not a peculiarity of Imgur API, but rather a standard used by Implicit OAuth Flow. According to docs this is the only recommended way to use Imgur OAuth

Initially I started a discussion of this problem on Discord channel and it was suggested that the data after # character does not even reach Obsidian, but this assumption is wrong (for details refer to workaround section)

Proposed solution

So in protocol handler I would like to get the part of an URL after the hash character. From the example above I would like to get:

#access_token=ACCESS_TOKEN&token_type=Bearer&expires_in=3600

My suggestion is to add 2nd param to protocol handler, which would contain the URL part after #. This would not break the current API but extend it to get necessary data.

While opening obsidian://imgur-oauth#access_token=ACCESS_TOKEN&token_type=Bearer&expires_in=3600 I would expect to get:

this.registerObsidianProtocolHandler("imgur-oauth", (params, hash_url_part) =>{
    console.log(hash_url_part); // #access_token=ACCESS_TOKEN&token_type=Bearer&expires_in=3600
})

Current workaround (optional)

Not an acceptable workaround, but some findings related to the code responsible for parsing obsidian:// protocol URL.

Earlier I mentioned that there was an assumption on Discord chat that the tail of an URL after # does not even reach Obsidian at all. Below is how I made sure it is wrong and there is a way to parse access token from Obsidian. Consider main.js from Obsidian.asar (v. 0.11.13), lines 995-999:

let qIndex = url.indexOf('?');
let hIndex = url.indexOf('#', Math.max(0, qIndex));
if (hIndex >= 0) {
	hash = url.substr(hIndex + 1);
	url = url.substr(0, hIndex);
}

If I simply change the above lines to:

let qIndex = url.indexOf('#');
//let hIndex = url.indexOf('#', Math.max(0, qIndex));
//if (hIndex >= 0) {
//	hash = url.substr(hIndex + 1);
//	url = url.substr(0, hIndex);
//}

I will get the data I need:

This change is not a proposal. Just a demonstration that the data I need after the hash-character arrives to Obsidian. For proposed solution see corresponding section above.

5 Likes

This would truly help with images. Like @Kir mentioned this can open amazing opportunities for plugins like his.

Would love for this to happen!

1 Like

I would also love this for a plugin I am working on. Basically the same idea (need OAuth verification).

1 Like

Maybe it’s faster for Licat to see this if you ask this in the merged pull request in the obsidian-release repo?

I can add a way to retrieve the hash string from the ObsidianProtocolData object in the next release.

3 Likes

Thank you @Licat!

Hi @Licat. Is there any info - what version is it planned for? As I can see there is 0.12.4 and 0.12.5 already, but do not see anything related in release notes or obsidian.d.ts

It’s not documented, but already included in Obsidian v0.12.5:
open obsidian://test?vault=医学&query=MOC#t=123 produce:

you can use query-string - npm (npmjs.com) to parse hash if you need to.

3 Likes