Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

node/examples/bootstrappedAppESM/ : A redirection handler must be provided in the Node environment. but we can't have one #3175

Open
scenaristeur opened this issue Oct 6, 2023 · 7 comments
Labels
bug Something isn't working

Comments

@scenaristeur
Copy link

trying ~/dev/solid-client-authn-js/packages/node/examples/bootstrappedAppESM/src$ node authenticatedScript.mjs --clientId https://id.inrupt.com/my_user --oidcIssuer https://login.inrupt.com/ --clientSecret mypassword --resource https://otherpod.solidcommunity.net/profile/card

i've got this error

Error: A redirection handler must be provided in the Node environment.
    at Redirector.redirect (file:///home/user/dev/solid-client-authn-js/packages/node/dist/index.mjs:896:19)
    at AuthorizationCodeWithPkceOidcHandler.handleRedirect (file:///home/user/dev/solid-client-authn-js/packages/core/dist/index.mjs:349:25)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async ClientAuthentication.login (file:///home/user/dev/solid-client-authn-js/packages/node/dist/index.mjs:83:33)
    at async Session.login (file:///home/user/dev/solid-client-authn-js/packages/node/dist/index.mjs:1292:31)
    at async main (file:///home/user/dev/solid-client-authn-js/packages/node/examples/bootstrappedAppESM/src/authenticatedScript.mjs:37:3)

whereas in the doc , a handler is optional

image

and as we are on the server side, we can not have a url for redirection

@scenaristeur scenaristeur added the bug Something isn't working label Oct 6, 2023
@zg009
Copy link

zg009 commented Oct 7, 2023

Hey, I should probably leave this to @NSeydoux but I think I see your problem here.

You are using the AuthorizationCodeWithPkceOidcHandler class which implements AuthorizationCodeWithPkceOidcHandlerBase from core and requires a Redirector object on run. So, these lines are causing you the issue if I'm correct:

return this.handleRedirect({
oidcLoginOptions,
state,
codeVerifier,
targetUrl,

Right there is where it's giving options for you in handleRedirect.

And here is the actual error you're seeing, because if there are options but no options and/or handleRedirect function, which I am guessing by your command line arguments was set as undefined, you get your current error.

export default class Redirector implements IRedirector {
redirect(redirectUrl: string, options?: IRedirectorOptions): void {
if (options && options.handleRedirect) {
options.handleRedirect(redirectUrl);
} else {
throw new Error(
"A redirection handler must be provided in the Node environment.",
);

Could you possibly try using the ClientCredentialsOidcHandler class here ?

@NSeydoux
Copy link
Contributor

NSeydoux commented Oct 8, 2023

Hi @scenaristeur , thanks for reporting this.

I think your issue is the following: you are attempting to use the Client Credentials OpenID flow, which is suitable for scripts, or services acting on their own behalf (as opposed to the Authorization Code flow, which is suited for apps acting on the behalf of their user). In order to use the @inrupt/solid-client-authn-node library to authenticate a script without a browser redirect, you'll want to use static client registration by visiting this page: https://login.inrupt.com/registration.html. You'll get credentials for your client there, that you should be able to use instead of your username/password in the command line you shared.

Can you confirm this resolves the issue you are seeing?

@zg009 , thanks for responding to the issue! You're quite right, the issue is that the incorrect handler gets called, and it results in a handler expecting a redirect running, causing the observed issue. However, the handler selection is not up to the caller, it's all internal, and based on parameters provided by the caller. In this case, the exact issue is that the provided Client ID is an IRI, which is identified in the library as an instance of a Solid-OIDC client doing an Authorization Code flow. Replacing this with a Client ID generated by the registration service will cause the library to pick up the correct handler.

@scenaristeur
Copy link
Author

My goal is to build a plugin for Obsidian to save my notes on a POD https://docs.obsidian.md/Plugins/Getting+started/Build+a+plugin. or https://forum.obsidian.md/t/how-to-get-started-with-developing-a-custom-plugin/8157/4

But i don't know how i allow a user to login to his POD from this plugin

@zg009
Copy link

zg009 commented Oct 20, 2023

You would need to handle the SOLID-OIDC authentication flow, which prompts the user in a browser tab to allow the application (your Obsidian plugin) to perform operations against the resource server (the POD server).

I don't know anything about Obsidian, but with a quick glance, you would probably need to start the authentication flow in the window.onload method and use the solid-client-authn-browser package to send the user to the Inrupt or other OIDC provider service to let them login then redirect back to the Obsidian plugin. If you can't load other windows from the plugin, you may be out of luck as the SOLID-OIDC spec does not support the "implicit" authorization flow, and I don't think any of the current SOLID resource servers support it, either.

Once the user has authenticated and authorized, you would probably want your plugin to save the contents of the notes often or when the user performs a save action, you use the access token to write the notes to a resource in the POD server that the user has specified.

@scenaristeur
Copy link
Author

This is exactly my problem, with Solid login. I can not redirect to obsidian as the plugin is not a browser, but something like électron i think and i cannot usé redirection to a webpage. And that's what i tried to connect with another lib than solid-auth-browser and use a handleredirect or something like that to get user credential, and then use it to post. I know the basics, i've build some Solid apps for a while 😉

@zg009
Copy link

zg009 commented Oct 20, 2023

Is there any chance you could use the static client credentials flow by registering credentials at inrupt then providing them somewhere in the plugin environment or as a configuration file?

@scenaristeur
Copy link
Author

scenaristeur commented Oct 22, 2023

The problem this way is that i get a ClientID and a ClientSecret, that i can not use in a plugin, because a plugin in obsidian is a github repo / zipped release that a user install in his obsidian, and the ClientSecret would be accessible to that user. or should each user register my plugin as his own app ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants