Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1svGc0-00Df56-A3 for pgsql-hackers@arkaria.postgresql.org; Mon, 30 Sep 2024 13:38:53 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1svGbz-000WyL-Lt for pgsql-hackers@arkaria.postgresql.org; Mon, 30 Sep 2024 13:38:51 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1svGbz-000Wxv-5z for pgsql-hackers@lists.postgresql.org; Mon, 30 Sep 2024 13:38:51 +0000 Received: from mail-wr1-x42a.google.com ([2a00:1450:4864:20::42a]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1svGbs-001nT4-6R for pgsql-hackers@postgresql.org; Mon, 30 Sep 2024 13:38:49 +0000 Received: by mail-wr1-x42a.google.com with SMTP id ffacd0b85a97d-37cdbcb139cso2013964f8f.1 for ; Mon, 30 Sep 2024 06:38:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cybertec.at; s=cybertec.at; t=1727703522; x=1728308322; darn=postgresql.org; h=message-id:date:content-transfer-encoding:mime-version:comments :references:in-reply-to:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=H8syDFlteOaZ55wb2sinJvFPjLCaySOaqpLZ99MtBpQ=; b=T9NC2CQzYvzwsittS9gMP25JEXVSV9I4OVRBQj3GsjrMyrjJVxUR87oIwG/rNPzzyW Hu6lzTBtOrGn1MqxmGk/6L74XhgsLTudBNIJQ6quOZit3tIr3BosRUjFQGOpePpg0sA8 oMA2VkDDo++SluWzx2cHhJBFvIlMaCpFuDT8c= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727703522; x=1728308322; h=message-id:date:content-transfer-encoding:mime-version:comments :references:in-reply-to:subject:cc:to:from:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=H8syDFlteOaZ55wb2sinJvFPjLCaySOaqpLZ99MtBpQ=; b=jkyC1zL+HFALOmUGy0GCoZpy1a9rhfbPCdMLzznHbwg14hbiGXrexKjbcqIbchu3dI zplAZbrU3K8JAyvJwVphn9vQ6Q3HN1m6+nYumjTiSy4fcoHAOuRNQP7MKZvMeZZMRgvU 61vgNH8/pg3TG3Ks+rMEgtax5/mEc6yK6z4yOMfwXz0iE4KTobnSJKMTQMvHPPM3r60H RPX/CQZ0/25jVj2BuG/XsH4pZxmhHGmASrzUa6BstLBMndsqr341xeiN3WscQNudJG99 bw4ozJPCSwKvXr4TRHP2skf5QOxgzYUJ7PHacR7TVtacaju0HoBuZbAA9mSjkPRaIveo SBHA== X-Forwarded-Encrypted: i=1; AJvYcCUA3EnNWp6tTxDDXwyLHuspBvH1iu8eO39jFg/qVZ/lvNTXVy7gihfOVxsM7fZ4g/iAEphd15L7jsFP7G7+@postgresql.org X-Gm-Message-State: AOJu0YztI6jhveMsn6EHab6j+7LBbQ+3c2gqGUxGRDteQr4IR6/a4b5Z IkdDs6vWnbiWMPHYlqZyd/JiVP+NGJeeLI28hookNV6GJKv9OBWFdoOx68eOOC22jjuM7KiYRq+ U X-Google-Smtp-Source: AGHT+IHm7GAVQEF8qLr2Aw301Tpazg3sTAabN/ua/ZHp3wyJyzIKAtN14v/CIqXHOJG7ILakV+aGmA== X-Received: by 2002:adf:fa4d:0:b0:37c:cbca:fd7c with SMTP id ffacd0b85a97d-37cd5ad1271mr7264105f8f.41.1727703522320; Mon, 30 Sep 2024 06:38:42 -0700 (PDT) Received: from antos (109-81-174-45.rct.o2.cz. [109.81.174.45]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-37cd56e6867sm9039174f8f.49.2024.09.30.06.38.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Sep 2024 06:38:41 -0700 (PDT) From: Antonin Houska To: Jacob Champion cc: Daniel Gustafsson , Peter Eisentraut , PostgreSQL Hackers Subject: Re: [PoC] Federated Authn/z with OAUTHBEARER In-reply-to: References: <3603e9bb-9a69-4761-869b-f5b1f204b840@eisentraut.org> <390f9699-6275-4e1e-a600-11452bee0576@eisentraut.org> <67b7e52e-0d6e-4eb5-9318-fdcfa4e7ea51@eisentraut.org> <20A6A78C-D5B1-4BA3-8CD0-99AF18A04B48@yesql.se> <4812.1727459899@antos> Comments: In-reply-to Jacob Champion message dated "Fri, 27 Sep 2024 13:45:45 -0700." X-Mailer: MH-E 8.6+git; nmh 1.8; GNU Emacs 28.2.50 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Date: Mon, 30 Sep 2024 15:38:41 +0200 Message-ID: <4503.1727703521@antos> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Jacob Champion wrote: > On Fri, Sep 27, 2024 at 10:58=E2=80=AFAM Antonin Houska = wrote: > > Have you considered sending the token for validation to the server, lik= e this > > > > curl -X GET "https://www.googleapis.com/oauth2/v3/userinfo" -H "Authori= zation: Bearer $TOKEN" >=20 > In short, no, but I'm glad you asked. I think it's going to be a > common request, and I need to get better at explaining why it's not > safe, so we can document it clearly. Or else someone can point out > that I'm misunderstanding, which honestly would make all this much > easier and less complicated. I would love to be able to do it that > way. >=20 > We cannot, for the same reason libpq must send the server an access > token instead of an ID token. The /userinfo endpoint tells you who the > end user is, but it doesn't tell you whether the Bearer is actually > allowed to access the database. That difference is critical: it's > entirely possible for an end user to be authorized to access the > database, *and yet* the Bearer token may not actually carry that > authorization on their behalf. (In fact, the user may have actively > refused to give the Bearer that permission.) > That's why people are so pedantic about saying that OAuth is an > authorization framework and not an authentication framework. This statement alone sounds as if you missed *authentication*, but you seem= to admit above that the /userinfo endpoint provides it ("tells you who the end user is"). I agree that it does. My understanding is that this endpoint, as well as the concept of "claims" and "scopes", is introduced by OpenID, which is an *authentication* framework, although it's built on top of OAuth. Regarding *authorization*, I agree that the bearer token may not contain enough information to determine whether the owner of the token is allowed to access the database. However, I consider database a special kind of "application", which can handle authorization on its own. In this case, the authorization can be controlled by (not) assigning the user the LOGIN attribute, as well as by (not) granting it privileges on particular database objects. In short, I think that *authentication* is all we need. > To illustrate, think about all the third-party web services out there > that ask you to Sign In with Google. They ask Google for permission to > access your personal ID, and Google asks you if you're okay with that, > and you either allow or deny it. Now imagine that I ran one of those > services, and I decided to become evil. I could take my legitimately > acquired Bearer token -- which should only give me permission to query > your Google ID -- and send it to a Postgres database you're authorized > to access. >=20 > The server is supposed to introspect it, say, "hey, this token doesn't > give the bearer access to the database at all," and shut everything > down. For extra credit, the server could notice that the client ID > tied to the access token isn't even one that it recognizes! But if all > the server does is ask Google, "what's the email address associated > with this token's end user?", then it's about to make some very bad > decisions. The email address it gets back doesn't belong to Jacob the > Evil Bearer; it belongs to you. Are you sure you can legitimately acquire the bearer token containing my em= ail address? I think the email address returned by the /userinfo endpoint is one of the standard claims [1]. Thus by returning the particular value of "emai= l" from the endpoint the identity provider asserts that the token owner does h= ave this address. (And that, if "email_verified" claim is "true", it spent some effort to verify that the email address is controlled by that user.) > Now, the token introspection endpoint I mentioned upthread Can you please point me to the particular message? > should give us the required information (scopes, etc.). But Google doesn't > implement that one. In fact they don't seem to have implemented custom > scopes at all in the years since I started work on this feature, which ma= kes > me think that people are probably not going to be able to safely log into > Postgres using Google tokens. Hopefully there's some feature buried > somewhere that I haven't seen. >=20 > Let me know if that makes sense. (And again: I'd love to be proven > wrong. It would improve the reach of the feature considerably if I > am.) Another question, assuming the token verification is resolved somehow: wouldn't it be sufficient for the initial implementation if the client could pass the bearer token to libpq in the connection string? Obviously, one use case is than an application / web server which needs the token to authenticate the user could eventually pass the token to the datab= ase server. Thus, if users could authenticate to the database using their individual ids, it would no longer be necessary to store a separate userid / password for the application in a configuration file. Also, if libpq accepted the bearer token via the connection string, it would be possible to implement the authorization as a separate front-end applicat= ion (e.g. pg_oauth_login) rather than adding more complexity to libpq itself. (I'm learning this stuff on-the-fly, so there might be something naive in my comments.) [1] https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims --=20 Antonin Houska Web: https://www.cybertec-postgresql.com