# Unable to Successfully Authenticate with Custom Solid OIDC Server in Client App

**URL:** <https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718>\
**Category:** Solid App Development FAQs\
**Created:** [July 31, 2025, 4:57pm UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718 "2025-07-31T16:57:08Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![jacobdaniel](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/jacobdaniel/32/4222_2.png) [@jacobdaniel](https://forum.solidproject.org/u/jacobdaniel)\
**Post date:** [July 31, 2025, 4:57pm UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/1 "2025-07-31T16:57:08Z")

</div>

Hello,

I’m developing a Solid application using the `@inrupt/solid-client-authn-browser` library and attempting to authenticate with my own Solid OIDC server instance hosted at:

[https://gardenmap.jacobdaniel.co.uk/](https://gardenmap.jacobdaniel.co.uk/)

I manage this server myself (Community Solid Server – CSS) and have successfully:

- Created a user and Pod.

- Logged into 3rd-party Solid apps using this server, which confirms the server works and issues tokens correctly.

* * *

What I’m Trying to Do

Set up a basic login flow in a browser app using:

`await login({ clientId: "...", clientSecret: "...", // also tried PKCE-only login without secret redirectUrl: "http://localhost:3003/callback", oidcIssuer: "https://gardenmap.jacobdaniel.co.uk/", scopes: ["openid", "profile", "offline_access"], });`

Followed by:

`await handleIncomingRedirect(window.location.href); `

Goal: Authenticate and retrieve a WebID via `getDefaultSession().info.webId`.

Problem - the login flow **fails at various stages** depending on configuration. Issues observed:

- `login()` call sometimes fails with:

- `.oidc/reg` endpoint responds with 400 despite valid payload.

- When testing login manually (e.g. via cURL), I receive a client ID and secret, but the app still fails to complete login via SDK.

- In `handleIncomingRedirect()`, `session.info.isLoggedIn` remains `false`, and `session.info.webId` is `undefined`.

- GET requests to `.oidc/reg` in browser return “Resource Not Found”.

Despite all this, I am able to authenticate using this same server in other Solid apps, so the server itself seems functional.

* * *

What I have tried

1. Successfully registered a client with POST to `/.oidc/reg`:

2. Confirmed proper authorization code flow:

3. Used session.handleIncomingRedirect():

4. Tested both PKCE and client\_secret-based flows.

5. Logged in successfully from another Solid App using this same server.

6. Manually verified token response via **`curl`** and verified correct WebID issued.

7. Inspected logs on server for:

* * *

Thoughts

- Something in the login flow config (client app side) is not aligning with what the Solid server expects.

- Possibly session state isn’t persisting across the login + callback flow in the app.

- Could also be an issue with dynamic client registration handling vs manual registration.

* * *

Help

- Is there a recommended pattern or minimal working example to authenticate against a custom CSS server from a browser app?

- How can I confirm that `handleIncomingRedirect()` is failing due to a specific error?

- Do I need to handle registration differently when using `@inrupt/solid-client-authn-browser`?

- Is it possible to skip the SDK’s `login()` and handle the OIDC steps manually (e.g. via fetch / URL manipulation)?

---

<div class="post-metadata">

**Author:** ![gaz009](https://avatars.discourse-cdn.com/v4/letter/g/a5b964/32.png) [@gaz009](https://forum.solidproject.org/u/gaz009)\
**Post date:** [July 31, 2025, 10:02pm UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/2 "2025-07-31T22:02:00Z")

</div>

Hello.

You asked a lot here so I will try and keep it short. The library you used is meant to work with Inrupt servers. They do some things differently than the CSS approach. I think in your login request you must request the ‘webid’ scope in order to receive the webid claim. That is probably why session.info.webId is undefined.

---

<div class="post-metadata">

**Author:** ![Vincent](https://avatars.discourse-cdn.com/v4/letter/v/e9bcb4/32.png) [@Vincent](https://forum.solidproject.org/u/Vincent)\
**Post date:** [August 1, 2025, 9:41am UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/3 "2025-08-01T09:41:21Z")

</div>

@gaz009 I don’t think that that is true - I have successfully used it to log in to non-Inrupt servers.

@jacobdaniel You have confirmed that the server works because you can use other apps with it, but it might be worth confirming the other side as well: does your app work with different servers? For example, can you log in to [https://solidcommunity.net](https://solidcommunity.net) with it?

I would at first try it without a client ID, to ensure it’s not broken because the client ID is invalid.

I also see you’re passing the arguments `clientSecret` and `scopes`, which [I don’t see listed in the docs](https://docs.inrupt.com/developer-tools/javascript/client-libraries/tutorial/authenticate-browser/). If you’re using generative AI to guide you, maybe best not to trust its suggestions, unless you verify it yourself in the docs. There also shouldn’t be a need to manually POST to anywhere - if you are using an AI, it sounds like it’s trying to mimic non-Solid login flows.

Also make sure that the redirect URL you’re pointing at (above, `http://localhost:3003/callback`) is the page where you’re calling `handleIncomingRedirect`.

If that’s not enough to get you there, it might be worth working through the docs I linked through above, see if you can at least get that to work?

---

<div class="post-metadata">

**Author:** ![renyuneyun](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/renyuneyun/32/3189_2.png) [@renyuneyun](https://forum.solidproject.org/u/renyuneyun)\
**Post date:** [August 1, 2025, 9:56am UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/4 "2025-08-01T09:56:54Z")

</div>

I think Vincent’s suggestions make a lot of sense. The library does work on other Solid server implementations, not just Inrupt’s.

Using it shouldn’t be complicated at all. In fact, the simplest way is to only pass three arguments to the `login()` function, as shown [here in the document](https://docs.inrupt.com/developer-tools/javascript/client-libraries/tutorial/authenticate-browser/#example):

```auto
    await login({
      oidcIssuer: "https://login.inrupt.com",
      redirectUrl: new URL("/callback", window.location.href).toString(),
      clientName: "My application"
    });

```

You passed many more arguments, and most of them I have never seen. I understand they may be needed eventually for the OIDC flow, but unnecessary (and potentially won’t work, as Vincent pointed out) for using this library as it will handle those things behind the scene.

Also, don’t forget to call `handleIncomingRedict()` in a sensible place. It’s not **physically** after the `login()` call, but **logically** after the `login()` call. This is because how OIDC and webpages works – it firsts redirects you to the OIDC issuer’s site, and redirect to your original app (webpage); but this second time you open your webpage, it starts from the beginning, rather than “resuming” from where you called `login()`.

---

<div class="post-metadata">

**Author:** ![jacobdaniel](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/jacobdaniel/32/4222_2.png) [@jacobdaniel](https://forum.solidproject.org/u/jacobdaniel)\
**Post date:** [August 1, 2025, 6:03pm UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/5 "2025-08-01T18:03:12Z")

</div>

Thanks all, and apologies for the messy post, I am picking up from my attempts at creating Solid App a few weeks ago, and indeed carelessly copied error debugging from AI assistance.

The docs for authenticating a user on a solid app with a community solid server do seem straight forward.

But I am still getting `400 bad request`. The payload shows `“redirect_uris”: [null]`

```javascript
"use client";
import React, { useEffect, useState } from "react";
import {
  login,
  getDefaultSession,
} from "@inrupt/solid-client-authn-browser";

export default function Home() {
  const [solidServer] = useState("https://gardenmap.jacobdaniel.co.uk");

  const [webId, setWebId] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const session = getDefaultSession();
    if (session.info.isLoggedIn) {
      setWebId(session.info.webId);
      setLoading(false);
    } else {
      setLoading(false);
    }
  }, []);

  const handleLogin = async () => {
    const callbackUrl = new URL("/callback", window.location.origin).toString();
    await login({
      oidcIssuer: solidServer,
      redirectUrl: callbackUrl,
      clientName: "My Solid App",
    });
  };

  return (
    <div>
      {loading && <p>Loading...</p>}

      {!loading && webId && (
        <>
          <p>Logged in as: {webId}</p>
        </>
      )}

      {!loading && !webId && (
        <>
          <p>Not logged in</p>
          <button
            className="border bg-white cursor-pointer p-2 py-1 rounded"
            onClick={handleLogin}
          >
            Login
          </button>
        </>
      )}
    </div>
  );
}

```

[Solid App](https://solidpod.jacobdaniel.co.uk/)

---

<div class="post-metadata">

**Author:** ![Vincent](https://avatars.discourse-cdn.com/v4/letter/v/e9bcb4/32.png) [@Vincent](https://forum.solidproject.org/u/Vincent)\
**Post date:** [August 1, 2025, 7:50pm UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/6 "2025-08-01T19:50:47Z")

</div>

It’s really hard to analyse that since there are some syntax errors in there, but it looks like your callback URL `/callback` doesn’t actually exist. As I understand it, you’re all just running it on the same page, `/` (aka `https://solidpod.jacobdaniel.co.uk`). So maybe instead of `callbackUrl` you just want to pass in `window.location.href`, i.e. since the page that has the call to `login` also has the `handleIncomingRedirect`, you just want to pass in the current page’s URL?

---

<div class="post-metadata">

**Author:** ![jacobdaniel](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/jacobdaniel/32/4222_2.png) [@jacobdaniel](https://forum.solidproject.org/u/jacobdaniel)\
**Post date:** [August 1, 2025, 9:28pm UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/7 "2025-08-01T21:28:10Z")

</div>

You’re quite right, I had the login and redirect handling on the same page (`/`), I’ve now separated concerns.

My `/callback` :

```javascript
"use client";
import { useEffect, useState } from "react";
import {
  handleIncomingRedirect,
  getDefaultSession,
} from "@inrupt/solid-client-authn-browser";
import { getSolidDataset, getThing, getIri } from "@inrupt/solid-client";
import Link from "next/link";

export default function CallbackPage() {
  const [webId, setWebId] = useState(null);
  const [podRoot, setPodRoot] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function completeLogin() {
      await handleIncomingRedirect();
      const session = getDefaultSession();
      if (session.info.isLoggedIn) {
        setWebId(session.info.webId);

        try {
          const profileDoc = await getSolidDataset(session.info.webId);
          const profile = getThing(profileDoc, session.info.webId);
          const podRoot = getIri(
            profile,
            "http://www.w3.org/ns/pim/space#storage",
          );
          setPodRoot(podRoot);
        } catch (err) {
          console.error("Error loading profile data:", err);
        }
      }

      setLoading(false);
    }

    completeLogin();
  }, []);

  return (
    <div>
      <h1>Callback Page</h1>
      {loading && <p>Loading...</p>}

      {!loading && webId && (
        <>
          <p>Logged in as: {webId}</p>
          {podRoot && <p>Pod Root: {podRoot}</p>}
        </>
      )}

      {!loading && !webId && (
        <div>
          <p>Not logged in.</p>
          <Link href="/" className="text-blue-400">
            Home
          </Link>
        </div>
      )}
    </div>
  );
}

```

Response:

```auto
{
    "name": "InvalidClientMetadata",
    "message": "invalid_redirect_uri",
    "statusCode": 400,
    "errorCode": "H400",
    "details": {},
    "error": "invalid_redirect_uri",
    "error_description": "redirect_uris must only contain strings"
}

```

---

<div class="post-metadata">

**Author:** ![Vincent](https://avatars.discourse-cdn.com/v4/letter/v/e9bcb4/32.png) [@Vincent](https://forum.solidproject.org/u/Vincent)\
**Post date:** [August 2, 2025, 8:30am UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/8 "2025-08-02T08:30:55Z")

</div>

OK, if I’m following correctly, that’s what your Solid server returns before you’re sent back to `/callback` - and it seems to say that you’re passing an invalid redirect URL.

Could you add a log just before your call to `login`, showing the value that you’re passing to its `redirectUrl` parameter?

---

<div class="post-metadata">

**Author:** ![jacobdaniel](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/jacobdaniel/32/4222_2.png) [@jacobdaniel](https://forum.solidproject.org/u/jacobdaniel)\
**Post date:** [August 2, 2025, 10:26am UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/9 "2025-08-02T10:26:40Z")

</div>

Yes. I understand that the `redirectUrl` needs to be a proper, fully qualified string, so I have tested using both hardcoded string and dynamic URL object, both logs just before `login()` is called appear as clickable links:

```auto
callback url: http://localhost:3002/callback 
solid server url: https://gardenmap.jacobdaniel.co.uk/

```

Additionally, in my `/callback` page I log:

```javascript
 console.log("Before redirect handling:", window.location.href);
 await handleIncomingRedirect();
 console.log("After redirect handling:", window.location.href);

```

Console:

```auto
Before redirect handling: http://localhost:3002/callback?code=hvu02XVxCdzv3_q4hY7V285PTn1hQnt6Quoxfox6H7D&state=5bf56dff4d06464290efa79b910a6e68&iss=https%3A%2F%2Fgardenmap.jacobdaniel.co.uk%2F
page.jsx:19 
After redirect handling: http://localhost:3002/callback

```

This suggests I am providing the `redirectUrl` value correctly and makes me wonder why I get `response error`?

I have tried setting the `oidcIssuer` to `https://solidcommunity.net` server and get the same error.

---

<div class="post-metadata">

**Author:** ![Vincent](https://avatars.discourse-cdn.com/v4/letter/v/e9bcb4/32.png) [@Vincent](https://forum.solidproject.org/u/Vincent)\
**Post date:** [August 4, 2025, 6:33am UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/10 "2025-08-04T06:33:45Z")

</div>

Hmm yeah, that all looks OK. Could you tell us which URL is sending that `InvalidClientMetadata` response that you posted above?

---

<div class="post-metadata">

**Author:** ![jacobdaniel](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/jacobdaniel/32/4222_2.png) [@jacobdaniel](https://forum.solidproject.org/u/jacobdaniel)\
**Post date:** [August 4, 2025, 10:26am UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/11 "2025-08-04T10:26:53Z")

</div>

Both server URLs l mentioned, `solidcommunity.net` and my personal server show that response.

---

<div class="post-metadata">

**Author:** ![Vincent](https://avatars.discourse-cdn.com/v4/letter/v/e9bcb4/32.png) [@Vincent](https://forum.solidproject.org/u/Vincent)\
**Post date:** [August 4, 2025, 11:18am UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/12 "2025-08-04T11:18:26Z")

</div>

We’ll need the full URL to be able to say anything meaningful though - I want to know which step in the authentication flow it is, and what is being communicated between the app and the Pod 🙂

---

<div class="post-metadata">

**Author:** ![jacobdaniel](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/jacobdaniel/32/4222_2.png) [@jacobdaniel](https://forum.solidproject.org/u/jacobdaniel)\
**Post date:** [August 4, 2025, 12:06pm UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/13 "2025-08-04T12:06:02Z")

</div>

Network during login:

When I log in using both `https://solidcommunity.net` and my own server `https://gardenmap.jacobdaniel.co.uk`, I see a successful response to the `/.oidc/reg` request with status `201 Created`. Here’s the payload being sent:

```auto
{
    "client_name": "My Solid App",
    "application_type": "web",
    "redirect_uris": [
        "http://localhost:3002/callback"
    ],
    "subject_type": "public",
    "token_endpoint_auth_method": "client_secret_basic",
    "id_token_signed_response_alg": "ES256",
    "grant_types": [
        "authorization_code",
        "refresh_token"
    ]
}

```

So registration doesn’t appear to be the issue. However, after I approve the login on the CSS (Pivot) interface, I’m redirected to `/callback` and that’s where I see the `InvalidClientMetadata` error in the page response.

I previously posted the URL before and after calling `handleIncomingRedirect()`:

This happens with both servers.

I thought the issue could be related to my use of `http://localhost` for the app, given that my CSS is on `https`, but I get the same response on my own `https` hosted solidpod domain.

---

<div class="post-metadata">

**Author:** ![Vincent](https://avatars.discourse-cdn.com/v4/letter/v/e9bcb4/32.png) [@Vincent](https://forum.solidproject.org/u/Vincent)\
**Post date:** [August 4, 2025, 12:22pm UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/14 "2025-08-04T12:22:34Z")

</div>

Hmm, I think I’m misunderstanding. Would it be possible to share a screenshot of your browser window when you’re seeing the error response?

---

<div class="post-metadata">

**Author:** ![jacobdaniel](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/jacobdaniel/32/4222_2.png) [@jacobdaniel](https://forum.solidproject.org/u/jacobdaniel)\
**Post date:** [August 4, 2025, 1:45pm UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/15 "2025-08-04T13:45:56Z")

</div>

Sure, really appreciate your help with this!

Enabling “Preserve log” in the devtools has helped trace the network activity through the full auth

My solidpod domain is currently configured to authenticate with my hosted CSS in case you are able to test for yourself.

[https://solidpod.jacobdaniel.co.uk](https://solidpod.jacobdaniel.co.uk)

 ![solidpod-login-network](https://europe1.discourse-cdn.com/flex017/uploads/solidproject/original/2X/d/d81291acbf96e1e350b95e4088fd49169c2ec9e2.jpeg)

---

<div class="post-metadata">

**Author:** ![Vincent](https://avatars.discourse-cdn.com/v4/letter/v/e9bcb4/32.png) [@Vincent](https://forum.solidproject.org/u/Vincent)\
**Post date:** [August 4, 2025, 2:12pm UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/16 "2025-08-04T14:12:21Z")

</div>

That’s weird, it’s making a bunch of requests that I don’t see in my app, including the one to `/reg` that errors out. You don’t happen to have the full source code you’re using posted somewhere, by any chance? Nothing jumps out to me as the obvious cause, unfortunately.

---

<div class="post-metadata">

**Author:** ![jacobdaniel](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/jacobdaniel/32/4222_2.png) [@jacobdaniel](https://forum.solidproject.org/u/jacobdaniel)\
**Post date:** [August 4, 2025, 2:56pm UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/17 "2025-08-04T14:56:29Z")

</div>

> **[GitHub - Jacob-Daniel/solidpod](https://github.com/Jacob-Daniel/solidpod)**
>
> Contribute to Jacob-Daniel/solidpod development by creating an account on GitHub.

Thanks for taking a look!

---

<div class="post-metadata">

**Author:** ![Vincent](https://avatars.discourse-cdn.com/v4/letter/v/e9bcb4/32.png) [@Vincent](https://forum.solidproject.org/u/Vincent)\
**Post date:** [August 4, 2025, 7:05pm UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/18 "2025-08-04T19:05:27Z")

</div>

Well, I checked out your code and played around a bit, and then I noticed that you’re using an older version of `@inrupt/solid-client-authn-browser`. Upgrading that to the latest one allowed me to log in successfully. So you’re probably hitting a bug that was since fixed in that library.

(Also, apparently it had a whole slew of releases that I wasn’t aware of, so my knowledge of it is probably outdated anyway 😅)

---

<div class="post-metadata">

**Author:** ![jacobdaniel](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/jacobdaniel/32/4222_2.png) [@jacobdaniel](https://forum.solidproject.org/u/jacobdaniel)\
**Post date:** [August 4, 2025, 10:37pm UTC](https://forum.solidproject.org/t/unable-to-successfully-authenticate-with-custom-solid-oidc-server-in-client-app/9718/19 "2025-08-04T22:37:14Z")

</div>

Oh dear… that’s slightly annoying - I had run `pnpm update` but didn’t realise it wouldn’t upgrade to a newer major version without explicitly specifying it. I see `pnpm update <package>` is more reliable.

Anyway, I am familiar with the login flow now 🫩

Thank you for going over it with me Vincent!
