go-gitea / gitea

Git with a cup of tea! Painless self-hosted all-in-one software development service, including Git hosting, code review, team collaboration, package registry and CI/CD
https://gitea.com
MIT License
45.29k stars 5.51k forks source link

OAuth2 - Additional Scopes Not Recognized For Required Claim Name/Value #31612

Open MAXimized490 opened 4 months ago

MAXimized490 commented 4 months ago

Description

Configuring the Discord OAuth2 authentication provider works without issues until you try to restrict login with additional scopes.

Here is a basic configuration of the Discord provider: Client ID: <your app id> Client Secret: <your app secret> Additional Scopes: guilds

Using this configuration, users are able to login/register via Discord without issues. Now lets try to restrict login to server membership. Looking at the Discord API docs, we see that the guilds scope will provide an id claim with the value being the server's ID. With this, we should be able to specify the necessary values.

Client ID: <your app id> Client Secret: <your app secret> Additional Scopes: guilds Required Claim Name: id Required Claim Value: <server id>

This will fail, resulting in the "Sign In Prohibited - Your account is prohibited from signing in, please contact your site administrator." Various alternate configurations of these values have been tried and none of them work. Because these values nor the countless I've tried have worked, I am opening this issue because either I am incorrectly configuring these settings or Gitea is not parsing the API response properly.

One thing of note is that the description for the Required Claim Value reads, "Set this value to restrict login from this source to users with a claim with this name and value." I cannot tell whether this description is purposefully worded this way, as I would assume this doesn't make sense when I can specify a required claim name separately. Regardless, trying to enter the entire claim or just the value here does not work either.

Quick Note on Logs Logs were copied after a fresh start of the docker container and then attempting to sign in with Discord with the required claim fields filled out. Since users are able to sign in when these fields are empty, I assume those logs are irrelevant.

Gitea Version

1.22.1

Can you reproduce the bug on the Gitea demo site?

No

Log Gist

https://gist.github.com/MAXimized490/c61f693111bc764389ca449cf3c5c6fb

Screenshots

image

image

Again, just a reminder that registration/login will work when the required claim fields are left blank.

Git Version

2.45.2

Operating System

Docker on Ubuntu Server 22.04

How are you running Gitea?

Using the official docker image via docker-compose on Portainer. Below is my compose file.

version: "3"

networks:
  gitea:
    external: false
  CENSORED:
    external: true

services:
  server:
    image: gitea/gitea:1.22.1
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=mysql
      - GITEA__database__HOST=db:3306
      - GITEA__database__NAME=gitea
      - GITEA__database__USER=CENSORED
      - GITEA__database__PASSWD=CENSORED

    restart: always
    networks:
      gitea:
      CENSORED:
        ipv4_address: CENSORED
    volumes:
      - gitea-data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "CENSORED:3000"
#      - "222:22"
    depends_on:
      - db

  db:
    image: mysql:8.0-oraclelinux8
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=CENSORED
      - MYSQL_USER=CENSORED
      - MYSQL_PASSWORD=CENSORED
      - MYSQL_DATABASE=gitea
    networks:
      - gitea
    volumes:
      - gitea-mysql:/var/lib/mysql

volumes:
  gitea-data:
  gitea-mysql:

Database

MySQL/MariaDB

MAXimized490 commented 4 months ago

After testing further, I have determined that setting the required claim name to id and the required claim value to a user's ID will successfully restrict login to that specific user. I still can't see how one is supposed to grab the claim name from the guilds scope since it also uses "id" as the name.

MAXimized490 commented 4 months ago

I did some further testing.

By default, Gitea will request the identify and email scopes. Setting Required Claim Name to any claim name expected within these scopes will work without issue. Going further and adding a Required Claim Value will again work as expected, limiting login to those with matching claims.

It's clear that adding guilds to the Additional Scopes (shown in original post) works because the Discord access request page will show that the application is requesting to see what servers the user is in, and removing guilds from Additional Scopes will make this disappear.

We can reliably test whether the guilds scope is working so long as we only use the identify, email, and guilds scopes. This is because the guilds scope has a few unique claims, notably "icon: "<fileID>" and "owner": "<bolean>". We've already determined that we can reliably test whether a scope's claims are being detected by simply setting the Required Scope Name and leaving the Required Scope Value blank. Trying this with icon or owner does not work, indicating that Gitea is not seeing these claims. Again, setting these back to a claim name from identify/email will work as expected.

lunny commented 3 days ago

Related to #32573

marcellmars commented 3 days ago

did you try to set required claimed name to name and then required claimed value just the name of the guild (as in string)?

marcellmars commented 3 days ago

Related to #32573

i think this is the flow when gitea allows discord's user to login into gitea. and the attempt is to reduce the logins to the users with the membership of specific guild.

32573 is the other way around when third party relies on gitea for the check if user could login or not.

it's very confusing because the vocabulary is the same. i'm very interested if i got this wrong and if this is related to #32573 so i have to change something there ;)