Inrupt pod login complains about an invalid_client

I’ve in the past created my own Solid authorization client Web::Solid::Auth - A Perl Solid Web Client - metacpan.org that seems to work for the Node and inrupt.net services using the DPoP authentication method.

Now I’m trying to update my code so that it also works for the newest, shiniest, pod.inrupt.com pods. I’m using, the latest Solid OIDC Primer from October 4 2021 as my guide for this.

The primer describes how I should publish a client_id document. So far so good, here it is: https://hochstenbach.inrupt.net/public/web-solid-auth.jsonld#this

Next I need to do an authorization request which should include the client_id plus redirect_uri (as specified in the client_id document). When I send this all to https://broker.pod.inrupt.com/authorization it just resonds with a JSON error resonse:

{
error: "invalid_client",
error_description: "Invalid remote client",
}

Is there some extra magic needed? What am I missing here?

I tried changeing the redirect_uri’s to public accessible servers, but that didn’t work.

1 Like

I think
@zwifi has worked on the js lib and could help

1 Like

It sounds like you are using static client id, is that right? i.e., https://hochstenbach.inrupt.net/public/web-solid-auth.jsonld#this. Does pod.inrupt.com support that? So far all my use has been with dynamic registration.

Right, it was not clear for me how to figure out what types of clients are supported by what type of platform.

1 Like

That’s an excellent question. I’d too like to know the answer. I’d really like to have a document/page that explains the differences across different platforms/servers.

1 Like

That’s an excellent question. Supported features should be discoverable through the .well-known/openid-configuration document. The Solid-OIDC specification mandates that an Identity Provider should specify its support for the specification required features by including "solid_oidc_supported": "https://solidproject.org/TR/solid-oidc" in its configuration document. However, the specification being still a moving target, this doesn’t solve all of the issues. That’s where the automated test suite comes into play: hopefully, we can write tests for each specification feature, and publish the results so that it’s clear what is supported by whom. In the meantime, we may need to manually document this, I opened a related specification issue to see what can be done.

All this to say that yes, Client ID documents are supported by https://broker.pod.inrupt.com/authorization. You’ll notice that the error message mentions that the client is remote, which is specific to Client ID documents, so the Identity Provider understood the intent, but it looks like the identifier doesn’t match the expected shape. Nothing jumps at me looking at the client document, but could you provide the whole request to the authorization endpoint for additional context ? For instance, can you confirm that the provided redirec_uri matches exactly http://localhost:3000/callback (no additional slash or query parameters) ?

PS: thanks @Smag0 for tagging me :slight_smile:

2 Likes

Thanks for this clarification! I’ve tested again and it all runs smoothly now. Maybe a temporary hiccup. It would be great to have a clarification in in the documents (human,machine readable) which kinds of clients are supported by an Pod/

To try this out myself, I made a client id document:
https://pod.inrupt.com/neeblaapp/public/auth.jsonld#this

And I made this authorization request:

https://broker.pod.inrupt.com/authorization?client_id=https://pod.inrupt.com/neeblaapp/public/auth.jsonld%23this&scope=profile%20webid%20offline_access%20openid&state=_kaJx-L_CdJ7RruDHdTCio3apVbQEm6GkMbuxKnmaC0&code_challenge=OLa4derV7kHhK2NQFzXzmILgj_jkcz3chhcfeK_wjjY&response_type=code&code_challenge_method=S256&redirect_uri=biz.SpasticMuffin.Neebla.solidSignIn:/config&nonce=jZ5ktoLUTLxeuCnnAxQct93ZdImNHhWjSmSY4YwpYMQ

And I get what hochstenbach initially reported:

Screen Shot 2021-10-16 at 9.56.31 PM

And the situation doesn’t change after trying it a few times.

Thoughts?

Indeed, also at my end I have again the same issue with the request that worked 5 days ago. It seems to be a temporary issue at the broker service at Inrupt.

This is my request:

https://broker.pod.inrupt.com/authorization?client_id=https%3A%2F%2Fhochstenbach.inrupt.net%2Fpublic%2Fweb-solid-auth.jsonld%23this&scope=openid%20profile%20offline_access&state=LshvllQv7BG9zBz6HY8Ne-jbb5ZUL-wRvcwc-h2PDXsu8G-WVC_sEb3MHPodjw17&response_type=code&code_challenge_method=S256&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&code_challenge=1hPqdUwZAoAs1ShgQJdphwYrLaXSCqyKqahHFSDldC8

@zwifi Any thoughts on this? Thanks!

I’ve also got dynamic registration working fine but not client id documents.

My understanding was that the server only checks that the document obtained when fetching the client id includes the redirect_uri.
Both the examples above seem to satisfy this.

I assume this means that the server either checks other properties too, has other validation requirements, or somehow failed to retrieve the client identifier document.

It looks like community-server (WebIdAdaptorFactory) checks the context and client_id too.
It then uses the oidc-provider library, which might have additional requirements?

I also had trouble with both local and non-local redirect_uris, but would understand if local redirects were prohibited.

In my case I added a debug line in client_schema.js of node-oidc-provider, which is imported by the community server and found that the issue was that the webid scope is not yet supported.

For @hochstenbach that doesn’t seem to be the problem given webid is already omitted.
For @crspybits that might to the trick (while recognising that omitting the webid scope might cause problems down the line)

I can confirm solidweb.me and broker.pod.inrupt.com both successfully redirected me to the login screen, i.e. the client identifier document was accepted.

Hey, Thanks! I changed https://pod.inrupt.com/neeblaapp/public/auth.jsonld#this to remove the webid scope, and retried with broker.pod.inrupt.com and got the same result-- Invalid remote client.

solidweb.me fails too, but the output is more interesting to me:

Screen Shot 2021-11-01 at 7.18.54 PM

It could be in this case (and perhaps with broker.pod.inrupt.com too?) it is assuming the client is web based. i.e., my redirect URI is

biz.SpasticMuffin.Neebla.solidSignIn:/config

For mobile applications and specifically, iOS, there are different constraints on the redirect URI. I’m going to try changing the redirect URI at least for a test and see what happens.

I changed the redirect URI to–

https://www.SpasticMuffin.biz/redirect

That further change produced the expected user sign-in UI on the redirect for solidweb.me.

Trying it with broker.pod.inrupt.com still produces Invalid remote client.

So, some forward progress!

1 Like

It might be worth reporting to CSS github if non-web redirects are not supported, and to Inrupt if CSS supports the client id document and ESS doesn’t.

When I go to https://broker.pod.inrupt.com/ and I try to login I get the error: {"error":"invalid_client","error_description":"Invalid client_id"}. Any idea?

Edit: Before I was using Chrome so I tried another browser (Firefox) and there it is working…

Hi @dieter,

Which application are you using to login?

Thanks,
Nick.-

Before I was also getting the error when I was browsing directly to the https://broker.pod.inrupt.com page, now I get the error only in Chrome (Firefox still works) when running a simple application where I’m using some solid-ui-react components:

import React, { useEffect, useState } from 'react'
import {
  LoginButton,
  LogoutButton
} from '@inrupt/solid-ui-react'
import { handleIncomingRedirect } from '@inrupt/solid-client-authn-browser'
import _ from 'lodash'

const App = () => {
  const [idp] = useState('https://broker.pod.inrupt.com')
  const [currentUrl] = useState("http://localhost:8080")
  const [auth, setAuth] = useState(false)

  const logout = () => {
    setAuth(false)
  }

  useEffect(() => {
    handleIncomingRedirect({
      restorePreviousSession: true
    }).then(async info => {
      setAuth(info)
      console.log(`Logged in with WebID [${info.webId}]`)
    })
  }, [])

  return (
    <div>
      <LoginButton
        authOptions={{ clientName: 'test' }}
        oidcIssuer={idp}
        redirectUrl={currentUrl}
        onError={console.error}
      ></LoginButton>
      <LogoutButton
        onLogout={logout}
      ></LogoutButton>
      {auth.isLoggedIn ? 'yes' : 'no'}<br />
    </div>
  )
}

export default App

Could you share the sequence of network interactions between the application and https://broker.pod.inrupt.com ? From the code snippet you shared, it looks like you’re not using a Client Identifier (an IRI to a JSON-LD document containing client information), so your client should go though Dynamic Client Registration. You should see a request to the identity Provider .well-known/oidc-configuration document, followed by a POST to a /registration endpoint. Then, the window should be redirected to the Identity Provider for you to log in, and finally there should be a POST to the /token endpoint. This last POST should have a base-64 value in the Authorization header. If you decode the value, it should follow the pattern <client id>:<client secret>, with the id and secret matching the values returned in the response from the /registration endpoint. Can you confirm that it is the case ?

If not, one thing to note if that the Inrupt React components expect to be wrapped in the SessionProvider component (see the storybooks examples or the doc’s sample app). Not doing so may still work because the default session is used in both cases, but that may be causing your issue.