solid-spec icon indicating copy to clipboard operation
solid-spec copied to clipboard

The solid:oidcIssuer mechanism is unsafe

Open RubenVerborgh opened this issue 5 years ago • 18 comments

If your WebID is hosted on domain X, but your Solid pod is on domain Y ≠ X, then you need the following statement in your profile:

<#me> solid:oidcIssuer <Y>.

Unfortunately, this mechanism is broken. Consider the following example.

  • Suppose my WebID is https://ruben.verborgh.org/profile/#me
  • Suppose my datapod is on https://solid.community/
  • Then I would add <#me> solid:oidcIssuer <https://solid.community> to my profile.
  • However, this means that anyone creating an account on https://solid.community can pretend to be me if they fill out my WebID upon registration.

RubenVerborgh avatar Aug 20 '18 16:08 RubenVerborgh

Interesting! That's a very good point. I didn't have external WebID functionality (hosted on a different server than the issuer) in mind when I proposed the solid:oidcIssuer mechanism.. (that functionality was added afterwards).

Good catch.

dmitrizagidulin avatar Aug 20 '18 16:08 dmitrizagidulin

We might consider killing the “external WebID” functionality altogether.

RubenVerborgh avatar Aug 20 '18 16:08 RubenVerborgh

I was just thinking that..

dmitrizagidulin avatar Aug 20 '18 16:08 dmitrizagidulin

Would that mean for WebID-OIDC authn your WebID and your authentication server, must live on the same domain?

The core idea of WebID is that it can be hosted anywhere.

melvincarvalho avatar Aug 20 '18 16:08 melvincarvalho

Maybe we can do something where you specify in your WebID profile not just the authorized oidcIssuer, but what your id on that issuer is. That could address the impersonation issue.

dmitrizagidulin avatar Aug 20 '18 16:08 dmitrizagidulin

Would that mean for WebID-OIDC authn your WebID and your authentication server, must live on the same domain?

I would like to keep the functionality. Tim, Amy, myself, and some others use it.

Maybe we can do something where you specify in your WebID profile not just the authorized oidcIssuer, but what your id on that issuer is.

Then we'd need some way to verify that. This information is currently not passed.

RubenVerborgh avatar Aug 20 '18 16:08 RubenVerborgh

Wouldnt your ID on the authn server be your WebID?

How about this. When signing up, you would add the predicate, if it is not there already, else throw an error?

melvincarvalho avatar Aug 20 '18 16:08 melvincarvalho

Then we'd need some way to verify that. This information is currently not passed.

True.. althoughhh... it would only need to be verified at signup, not with every authentication. So, you'd add another triple to your WebID Profile, be like, solid:account <https://ruben.solid.community> or something. And then at signup, the server would check - are you signing up to be account name ruben, and if yes, that's fine. And subsequent users can't also put in your external webid and impersonate.

dmitrizagidulin avatar Aug 20 '18 16:08 dmitrizagidulin

Why not make each subdomain created for users an issuer for that user, this way you would have simply <#me> solid:oidcIssuer <https://ruben.solid.community> <https://ruben.verborgh.org/profile/> .

BTW even if issuer stays https://solid.community (without user specific subdomain) it still seems that in worst case one can only create an account for WebID one doesn't own and prevent holder of that WebID to create account on the same pod. As long as pod only allows one account for given WebID, if Alice created an account for WebID owned by Bob, and later Bob tries to create account on the same pod for his WebID, the pod will reject that operation and Bob will never end up adding that pod as an issuer to one's WebID profile. This way one can't really impersonate someone else since pod with 'squatted' account for given WebID will never appear as issuer in that WebID profile.

elf-pavlik avatar Aug 21 '18 04:08 elf-pavlik

I think @elf-pavlik makes a good point.

I was just debugging some oidcIssuer problems with @RubenVerborgh

I had set my oidcIssuer to the subdomain, but found out I need to set it to the root.

Does it not make more sense to set it to the subdomain. Consider, also if a user wants to use a CNAME e.g. drive.user.com to point to their storage, for portability. Wouldnt they also want to point oidcIssuer to that CNAME?

melvincarvalho avatar Aug 21 '18 19:08 melvincarvalho

A totally different direction is to drop the issue mechanism altogether, and replace it with a sameAs mechanism for accounts.

RubenVerborgh avatar Aug 21 '18 19:08 RubenVerborgh

OpenID Connect Discovery has a spec https://openid.net/specs/openid-connect-discovery-1_0.html

Even though Solid doesn't use webfinger and instead of using defined in that spec http://openid.net/specs/connect/1.0/issuer link relation uses predicate in solid: namespace, it still uses similar mechanism to discover issuer.

I don't see exactly how you see using sameAs but it seems like drifting even further away from OpenID Connect Discovery.

elf-pavlik avatar Aug 21 '18 21:08 elf-pavlik

Chatted a bit to @dmitrizagidulin on gitter, a couple of things seem logical to me

  • if you claim a WebID on an oidc issuer, the IdP should, at a minimum, check that linkage

  • the WebID-OIDC spec needs to be changed, imho, in order to claim WebID compliance. Any IdP MUST allow the WebID as a login principal, it MAY use a local host specific nick (the user@host pattern)

We can break out the 2nd point into a new issue.

EDIT: I actually thought part 2 was always the case, that you could EITHER type in your WebID or your IdP / nick

melvincarvalho avatar Aug 22 '18 05:08 melvincarvalho

As an aside, for those using the more secure WebID-TLS (which should be encouraged), the oidcIssuer predicate (which increases the attack surface) should not be needed. This is because all servers should be TLS capable, at least on one URI, so dont need to check the oidcIssuer, as the check is done in the TLS handshake. This gives users an upgrade path to a more secure and passwordless UX.

melvincarvalho avatar Aug 22 '18 05:08 melvincarvalho

As an aside, for those using the more secure WebID-TLS (which should be encouraged), the oidcIssuer predicate (which increases the attack surface) should not be needed.

Indeed, this is captured in https://github.com/solid/node-solid-server/issues/755

RubenVerborgh avatar Aug 22 '18 14:08 RubenVerborgh

Would that mean for WebID-OIDC authn your WebID and your authentication server, must live on the same domain?

I would like to keep the functionality. Tim, Amy, myself, and some others use it.

Maybe we can do something where you specify in your WebID profile not just the authorized oidcIssuer, but what your id on that issuer is.

Then we'd need some way to verify that. This information is currently not passed.

If the user can retrieve its sub claim, what could work would be to add in the WebID a claim to a iss/sub pair rather than only the iss (as it is specified right now). This would create a two-way relationship between the WebID and the OIDC identity.

However (and it is a big one), the OIDC specification does not specify that the sub identifier is unique. In practice, a user may have multiple sub identifier, for instance one for each audience aud he has authorized (client websites). So there is a chicken and egg issue because during enrollment on the client website the user would not know in advance his sub as it will be generated by the IdP after the client requested the user identity. And a workload issue because the user would have to add an iss/sub pair for each audience for which he wants to assert its WebID.

I do not know other identifiers specified by OIDC which could be used to link the WebID to the OIDC identity.

Sparika avatar Apr 03 '19 17:04 Sparika

I thought https://github.com/solid/webid-oidc-spec was the repo for WebID-OIDC stuff?

@Sparika not sure you are describing the same thing but check my proposal on how WebID URI can be derived from the ID token: https://github.com/solid/webid-oidc-spec/issues/10

namedgraph avatar Apr 03 '19 20:04 namedgraph

For future reference, this is how CSS does it: https://github.com/solid/community-server/blob/e8a0f63e0284bd69d3c5b265ebf108ab3550434f/src/identity/ownership/TokenOwnershipValidator.ts

Essentially by checking whether a randomized ID is present, and that ID corresponds to one specific pod (as opposed to an entire server).

RubenVerborgh avatar Jun 15 '21 20:06 RubenVerborgh