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

Allow RPs to provide their own terms of service and privacy policy URLs for "configURL: any" option #8

Open
aaronpk opened this issue May 13, 2024 · 16 comments

Comments

@aaronpk
Copy link

aaronpk commented May 13, 2024

With the configURL: "any" option, it's possible (and likely) that the RP will not have a prior relationship to the IdP. This means there is no registration data the IdP can pull the terms of service and privacy policy URLs from. In these cases it would make more sense to let the RP provide its own URLs.

I am not exactly sure of the best solution to this, but wanted to file this issue while it's on my mind.

@samuelgoto
Copy link
Collaborator

samuelgoto commented May 13, 2024

Yeah, this seems like a plausible request, that would work within our privacy/security constraints.

Any precedence that we could use to follow here? Has this problem been solved before elsewhere?

A couple of things comes to my mind, that I don't know about enough, but figured that you might:

  1. Didn't one of the early version of OpenID allow you to name your OP by URI? And, if so, didn't that OP need the RP's terms of service and privacy policies before they could release a token?
  2. Wouldn't the dynamic client registration schemes help here? Isn't there a variation of it that we could use to allow the IdP to have these URLs?

I am not exactly sure of the best solution to this, but wanted to file this issue while it's on my mind.

If we were to solve this in browserland, I'm thinking maybe we could have a JS parameter that the RP could use to pass that? e.g.

const credential = await navigator.credentials.get({
  identity: {
    provider: [{
      configURL: "any",
      // .. other stuff
      termsOfService: "https://rp.example/tos.html",
      privacyPolicy: "https://rp.example/tos.html",
    }]
  }
});

@aaronpk
Copy link
Author

aaronpk commented May 13, 2024

maybe we could have a JS parameter that the RP could use to pass that?

Seems reasonable to me.

  1. didn't that OP need the RP's terms of service and privacy policies before they could release a token?

I don't remember this being a thing. I'm trying to dig up screenshots of how it used to work, but documentation is sparse. From what I remember, it only returned the URL, no additional information. I don't see anything in the original spec that indicates other profile info is returned either: https://openid.net/specs/openid-authentication-1_1.html

I found examples of two confirmation/consent screens that only described releasing the URL to the RP:

4287828449_10128c5155_o

2208370481_a99e5cb7bf_o

@samuelgoto
Copy link
Collaborator

Another option that occurred in this thread was to make client_id a URL that is de-referanceable with static JSON metadata:

https://socialhub.activitypub.rocks/t/federated-credentials-api-developer-feedback-needed/3961/17

So, one variation here is to have the RP pass a URL where we can get the TOS and PP from (and, as suggested in the thread, the RP's logo / name).

Example:

const credential = await navigator.credentials.get({
  identity: {
    // The browser gets the PP and TOS from this URL
    relyingParty: "https://rp.example/metadata.json",
    provider: [{
      configURL: "any",
      // .. other stuff
    }]
  }
});

@ThisIsMissEm @anderspitman FYI

@aaronpk
Copy link
Author

aaronpk commented May 21, 2024

That would work, in which case you'd probably want to reuse the existing properties from OAuth Dynamic Client Registration called tos_uri and policy_uri.

@ThisIsMissEm
Copy link

@samuelgoto why relyingParty here, when else where we have client_id? did that get renamed?

@ThisIsMissEm
Copy link

But we'd likely need to do:

relyingParty: {
  url: "..."
  format: "oauth2"
}

Since OAuth and OIDC can differ in some ways, and for the same reasons in w3c-fedid/FedCM#591

@samuelgoto
Copy link
Collaborator

Ah, fwiw, another option that occurred to me that was suggested in the past (I can't find it anymore! but I do remember that this was proposed at some point), was to come up with conventions on where to find the PP and TOS in websites through .well-known files.

So, the browser could use the links https://example.com/.well-known/privacy_policy and https://example.com/.well-known/terms_of_service, and the RP is responsible for 302-ing that to the right places.

I don't know if that's good or bad compared to the other alternatives, but figured it was worth noting it down so that we can compare and contrats.

@aaronpk
Copy link
Author

aaronpk commented Jun 25, 2024

Here is an early draft that lets the client provide all of its own metadata hosted at a URL. I've already built this in to webmention.io's FedCM implementation https://drafts.aaronpk.com/draft-parecki-oauth-client-id-metadata-document/draft-parecki-oauth-client-id-metadata-document.html

@samuelgoto samuelgoto transferred this issue from w3c-fedid/FedCM Sep 6, 2024
@yi-gu
Copy link

yi-gu commented Sep 27, 2024

Is it possible for the RP to render their own PP/TOS after receiving the token? Not sure if this has to be done from the browserland. A typical UX could be:

  1. User has gone through the FedCM flow without seeing PP/TOS
  2. Upon receiving the token, before completing the registration, ask users to grant further permissions in a customized UI with PP/TOS/whatever.
  3. If user accepts, proceed with sign-up; otherwise, drop the token and ideally call IdentityCredential.disconnect to reset the browser knowledge

@npm1
Copy link

npm1 commented Oct 25, 2024

I mean the same is technically true of the IDP-provided links, but you probably do not want to do the data exchange if a user has not agreed to the terms, so the idea above is probably not acceptable to any RP wishing to provide their own links.

@samuelgoto
Copy link
Collaborator

Here is an early draft that lets the client provide all of its own metadata hosted at a URL. I've already built this in to webmention.io's FedCM implementation https://drafts.aaronpk.com/draft-parecki-oauth-client-id-metadata-document/draft-parecki-oauth-client-id-metadata-document.html

@aaronpk can you help me understand how this works? how does the browser discovers the URL where the metadata is provided? Are you thinking this is a .well-known file? Or is that a JS browser API parameter?

@ThisIsMissEm
Copy link

@samuelgoto my understanding is that this is the relyingParty URL, which points to a value to use as the client_id

@samuelgoto
Copy link
Collaborator

samuelgoto commented Oct 28, 2024

@samuelgoto my understanding is that this is the relyingParty URL, which points to a value to use as the client_id

Ah, neat, thanks! That would work!!

I like how this is a URL, because it makes it resistant to client-side malicious code.

@ThisIsMissEm
Copy link

So yeah, rather than setting "relyingParty" to a pre-known value to use as client_id you set it to a URL of a Client ID Metadata Document, and then if the authorization server that the credentials API speaks to requires the client information, it goes off and fetches it before continuing.

@samuelgoto
Copy link
Collaborator

the authorization server that the credentials API speaks to requires the client information, it goes off and fetches it before continuing.

Just checking, but I was wondering if, from an ergonomics perspective, it wouldn't it be much easier for RPs to pass that information in JS rather than host an HTTP endpoint?

@aaronpk
Copy link
Author

aaronpk commented Oct 28, 2024

It's arguable about whether it's easier. Some would argue that an option that relies on no JavaScript is easier than using any JS. But in any case, the security model of this relies on it being at a URL. https://www.ietf.org/archive/id/draft-parecki-oauth-client-id-metadata-document-00.html#name-security-considerations

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants