External OIDC default scopes "openid" and "profile" cannot be changed or overridden

I’m submitting a…

  • Regression (a behavior that stopped working in a new release)
  • [v] Bug report
  • Performance issue
  • Documentation issue or request

Current behavior

When external OIDC enabled there is no way to pass single “openid” scope to external identity server. By default there will be at least “openid” and “profile” scopes passed. But the issue in our case is that our identity server didn’t setup to process “profile” scope. The only way for us now is to fork Squidex and develop workaround to be able to pass only single “openid” scope to identity server. In the snippet below there always will be scopes “openid” and “profile” as a options.Scope and no way to remove “profile” scope. That’s all because of the implementation that have hardcoded Scope values as:

Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectOptions

Scope.Add("openid");
Scope.Add("profile");

Our identity server /.well-known/openid-configuration

...
  "scopes_supported": [
    "offline_access",
    "offline",
    "openid"
  ],
...

Expected behavior

We would like to be able to disable other than “openid” default scopes or override default scopes. In case of first option we will have to do something like in our fork for squidex/backend/src/Squidex/Config/Authentication/OidcServices.cs at master · Squidex/squidex · GitHub

...
            authBuilder.AddOpenIdConnect(Constants.ExternalScheme, displayName, options =>
            {
                options.Scope.Clear();
                options.Scope.Add(OpenIddict.Abstractions.OpenIddictConstants.Scopes.OpenId);
...

Minimal reproduction of the problem

Run Squidex locally and setup any external OIDC with supported scopes as

...
  "scopes_supported": [
    "offline_access",
    "offline",
    "openid"
  ],
...

Environment

  • Self hosted with docker
  • Self hosted with IIS
  • [v] Self hosted with other version
  • Cloud version

Version: [VERSION]

Browser:

  • [v] Chrome (desktop)
  • Chrome (Android)
  • Chrome (iOS)
  • Firefox
  • Safari (desktop)
  • Safari (iOS)
  • IE
  • Edge

Others:

error: invalid_scope
error_description: The requested scope is invalid, unknown, or malformed. The OAuth 2.0 Client is not allowed to request scope 'profile'.

I think per spec those two scopes are basically required. Any change must also be backwards compatible.

Hello @Sebastian, thanks for the rapid reply! It doesn’t seems like those two scopes are basically reaquired as for OpenId Connect core specs:

3.1.2.1. Authentication Request


OpenID Connect uses the following OAuth 2.0 request parameters with the Authorization Code Flow:

scope
REQUIRED. OpenID Connect requests MUST contain the openid scope value. If the openid scope value is not present, the behavior is entirely unspecified. Other scope values MAY be present. Scope values used that are not understood by an implementation SHOULD be ignored. See Sections 5.4 and 11 for additional scope values defined by this specification.

And to be honest I don’t understand why implementation of Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectOptions hardcodes these two values

    public OpenIdConnectOptions()
    {
    ...
        Scope.Add("openid");
        Scope.Add("profile");

But the point of my post is not to understand why OpenIdConnectOptions is implemented this way, but to get your advice on a workaround to solve this problem without changing the Squidex source code. Maybe you have solved this problem somehow earlier? The main point is to be able to request single “openid” scope during external OIDC, without passing both “openid” and additional “profile”.

Technically also profile is required, because Squidex needs a username.

I can’t talk that much about the default implementation. If you find a way to make it configurable without breaking changes feel free to provider a PR.

Perhaps an additional flag or a syntax with -profile to remove the scope?