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

OAuth2 Provider実装 #8262

Closed
syuilo opened this issue Feb 7, 2022 · 16 comments · Fixed by #11053
Closed

OAuth2 Provider実装 #8262

syuilo opened this issue Feb 7, 2022 · 16 comments · Fixed by #11053
Assignees
Labels
✨Feature This adds/improves/enhances a feature 🔥high priority packages/backend Server side specific issue/PR

Comments

@syuilo
Copy link
Member

syuilo commented Feb 7, 2022

Summary

  • 要望が多い
  • 広く使われている方式のため、サードパーティアプリ開発者にやさしそう
  • 独自の実装はセキュリティ上の懸念がある
@syuilo syuilo added ✨Feature This adds/improves/enhances a feature packages/backend Server side specific issue/PR labels Feb 7, 2022
@syuilo syuilo mentioned this issue Dec 18, 2022
@syuilo
Copy link
Member Author

syuilo commented Dec 18, 2022

実装を試みたけど学習コスト高くて挫折

@rxy
Copy link

rxy commented Mar 9, 2023

OAuth2 Provider という認識であっていますか。
oidc-provider は「よさげ」にみえます。

ref: 【Node.js】expressでOAuth2プロバイダーを作ろう - Qiita

@tamaina
Copy link
Contributor

tamaina commented Mar 9, 2023

 あ、なんかこれめっちゃ楽そう

@saschanaz
Copy link
Member

saschanaz commented Mar 9, 2023

出来ればIndieAuthも考慮したいです (OAuth 2.0の個人サーバー向けの改良版)

Edit: でもいいライブラリがないかも
Edit 2: Mastodonにもリクエストありました mastodon/mastodon#24066

@syuilo syuilo changed the title OAuth2サポート OAuth2 Provider実装 Mar 9, 2023
@syuilo syuilo pinned this issue Mar 12, 2023
@syuilo
Copy link
Member Author

syuilo commented Mar 12, 2023

テスト込みで実装された方に報奨金を進呈

@saschanaz
Copy link
Member

saschanaz commented Mar 14, 2023

OAuth実装に.well-known/oauth-authorization-serverは必修ではないようですが、簡単なはずですので一緒に実装したいです(いろんなサーバーソフトウェアをサポートしたいクライアントがいちいちoauth endpointをハードコードしなくても済むように)

GitLabの実装: https://gitlab.com/.well-known/oauth-authorization-server (https://gitlab.com/gitlab-org/gitlab/-/issues/233956)
Mastodon: mastodon/mastodon#24099

@tamaina
Copy link
Contributor

tamaina commented Mar 14, 2023

いろんなサーバーソフトウェアをサポートしたいクライアントがいちいちoauth endpointをハードコードしなくても済む

神じゃん

@saschanaz
Copy link
Member

やるか(しゅいろさん風)

@saschanaz saschanaz self-assigned this Mar 18, 2023
@saschanaz
Copy link
Member

saschanaz commented Mar 18, 2023

現在の計画はこうです

  1. oidc-providerをつかう(ほかにいいものがなかったですので。oauth2orizeもありますがpassportという別のものも要求しているので複数そう)
  2. oidc-providerはOpenID専用のエンドポイントも沢山提供しますが、複雑になるしまずはOAuth2に必要なエンドポイントだけ提供するように (/oauth/authorize, /oauth/token)
  3. MiAuthのようにクライアントの登録が必要ない方向にする。この場合クライアント認証関連はIndieAuthで推薦している方法をつかう
    • client_idがURL形式であることを強制し、そのページからredirect_uriをもらって認証につかう
    • PKCEを強制する(本来は強制ではないが推薦はされてる)
    • OAuth2交換性は守る

Q: 登録しなくてもいいわけ?client_secretは?

つかいません。元々private APIを持つサービス向けのもので、全APIを公開しているMisskeyには要らないです。

複雑度を減らすため全クライアントに安全装置を強制する予定です(PKCEとかgrant_type=authorization_codeとか)

@saschanaz
Copy link
Member

saschanaz commented Mar 19, 2023

oauth2orizeに移したいです

  1. oidc-provider側のサポートが有料っぽい(https://github.com/panva/node-oidc-provider#support) 公開issue tracker自体がないので問題が発生した場合何をしたらいいのか分からなくなる可能性が高い。これではPRも書けない
  2. oauth2orizeの方が普通に人気(npmでweekly 80k, oidc-providerは~30k)
  3. oidc-providerの挙動が気に入らない(authorizeエンドポイントの画面で直接認証できず、HTTP 302で他のエンドポイントに移動して認証する必要がある。そのためにcookieを使うしそれをdbに保存もするので面倒)
    • oauth2orizeではrenderパラメーターを使える
  4. なぜDBにアクセスするのかが分かりにくく、いいログが書けない(client_idを探しているのか何なのか伝えてくれない。oauth2orizeではちゃんと分かれている)

@syuilo
Copy link
Member Author

syuilo commented Mar 20, 2023

oauth2orizeは最終コミットが2021年なのとJavaScriptで書かれているのが気になりはした

@saschanaz
Copy link
Member

oauth2orizeは最終コミットが2021年なのと

これちょっと気になりますね(でも死んでいるわけではないのでまあいいかと)

https://github.com/node-oauth/node-oauth2-server もありますが、かなり生まれたてですし必要な機能があるのかも怪しいです (node-oauth/node-oauth2-server#180)

一旦使えるoauth2orizeを使って、どうしてもだめならまた移すことにしようと思います

@Johann150
Copy link
Contributor

Q: 登録しなくてもいいわけ?client_secretは?

つかいません。元々private APIを持つサービス向けのもので、全APIを公開しているMisskeyには要らないです。
-- #8262 (comment)

Q: Why don't I have to get my client_secret registered?

You do not need to use it. It was originally intended for services with private APIs, and Misskey, which exposes all its APIs, doesn't need it.
-- (translated with deepl)

Are you sure about this? I do not think this is the correct understanding of RFC 6749 § 2.1. The distinction of whether a client_secret should be issued depends only on the client and has nothing to do with whether the resource server's API is public or not. For example Github issues client secrets even though their API is also as public as Misskey's API.

According to the RFC, Client secrets cannot be issued to clients which cannot keep it a secret (public client). Example: You write a mobile app for a website and need to register the client in advance on a web form. This means the client secret would need to be hard coded into the app. If you download the app you can find the string containing the secret inside it. This obviously means it is not actually a "secret" since anyone can find it out by just downloading the application.

In my opinion, all Misskey clients would be confidential clients because Misskey has dynamic client registration. If you want to read my opinion see also https://qwertqwefsday.eu/foundkey/oauth2.html#client-registration.

@saschanaz
Copy link
Member

Oh sorry, my previous description was indeed incorrect. Thank you for catching that.

That said, per the RFC:

public

Clients incapable of maintaining the confidentiality of their credentials (e.g., clients executing on the device used by the resource owner, such as an installed native application or a web browser-based application), and incapable of secure client authentication via any other means.

Obviously "clients executing on the device used by the resource owner, such as an installed native application or a web browser-based application" is the purpose here. Even if the client info is not hardcoded to the app, one must not assume anything sent to the random user device will be confidential.

On the contrary:

confidential

Clients capable of maintaining the confidentiality of their credentials (e.g., client implemented on a secure server with restricted access to the client credentials), or capable of secure client authentication using other means.

That basically means some server-side clients, perhaps something like https://elk.zone, on which users won't get the credentials on their device.

So I think my point still holds. My current plan for the initial implementation is to restrict things to public clients and defer anything else, to reduce initial complexity. The only accepted grant type will be authorization_code at least initially, and there will be no special auth flow even if a client is treated as "confidential".

@yuriha-chan
Copy link
Contributor

最初の実装ではあまり気にすることではないかもしれませんが…

分散SNSという環境上、SPの管理者が気が付かないうちにIdPが運営を終了することがあり得る。その場合、攻撃者は期限が切れたドメインを取得して、そのドメイン上で自分の管理下にある新しいIdPを運営することができる。すると、攻撃者は旧IdPのアカウントに紐づいているSPのアカウント全てにログインすることが可能となる。
ような気がする。

対策としては、SPが(公開鍵チャレンジレスポンスなどで)IdPサーバーを認証してからOpenID認証フローを実行すればよいと思われる。

--

In the Fedi world, it is possible for an IdP to silently shut down its services and the SP is unaware of it. In that case, the attacker can take the expired domain and run a new IdP under his/her control. The attacker can then access all SP accounts associated with the terminated IdP.

SPs could avoid this exploit by first validating the IdP server through challenge-response authentication (or anything) before initiating the OpenID authentication flow.

@saschanaz
Copy link
Member

(identity providerの実装はOAuth本体には含まれていないので、複雑さを下げるため別の作業にしたいと思います)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨Feature This adds/improves/enhances a feature 🔥high priority packages/backend Server side specific issue/PR
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants