Merge pull request #1824 from mgkbadola/discord-oauth

feat: Discord OAuth support
This commit is contained in:
Umputun
2024-11-18 14:57:31 -06:00
committed by GitHub
16 changed files with 66 additions and 9 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
Remark42 is a self-hosted, lightweight and simple (yet functional) comment engine, which doesn't spy on users. It can be embedded into blogs, articles, or any other place where readers add comments.
* Social login via Google, Facebook, Microsoft, GitHub, Apple, Yandex, Patreon and Telegram
* Social login via Google, Facebook, Microsoft, GitHub, Apple, Yandex, Patreon, Discord and Telegram
* Login via email
* Optional anonymous access
* Multi-level nested comments with both tree and plain presentations
+6
View File
@@ -107,6 +107,7 @@ type ServerCommand struct {
Yandex AuthGroup `group:"yandex" namespace:"yandex" env-namespace:"YANDEX" description:"Yandex OAuth"`
Twitter AuthGroup `group:"twitter" namespace:"twitter" env-namespace:"TWITTER" description:"[deprecated, doesn't work] Twitter OAuth"`
Patreon AuthGroup `group:"patreon" namespace:"patreon" env-namespace:"PATREON" description:"Patreon OAuth"`
Discord AuthGroup `group:"discord" namespace:"discord" env-namespace:"DISCORD" description:"Discord OAuth"`
Telegram bool `long:"telegram" env:"TELEGRAM" description:"Enable Telegram auth (using token from telegram.token)"`
Dev bool `long:"dev" env:"DEV" description:"enable dev (local) oauth2"`
Anonymous bool `long:"anon" env:"ANON" description:"enable anonymous login"`
@@ -321,6 +322,7 @@ func (s *ServerCommand) Execute(_ []string) error {
"AUTH_TWITTER_CSEC",
"AUTH_YANDEX_CSEC",
"AUTH_PATREON_CSEC",
"AUTH_DISCORD_CSEC",
"TELEGRAM_TOKEN",
"SMTP_PASSWORD",
"ADMIN_PASSWD",
@@ -952,6 +954,10 @@ func (s *ServerCommand) addAuthProviders(authenticator *auth.Service) error {
authenticator.AddProvider("patreon", s.Auth.Patreon.CID, s.Auth.Patreon.CSEC)
providersCount++
}
if s.Auth.Discord.CID != "" && s.Auth.Discord.CSEC != "" {
authenticator.AddProvider("discord", s.Auth.Discord.CID, s.Auth.Discord.CSEC)
providersCount++
}
if s.Auth.Dev {
log.Print("[INFO] dev access enabled")
+2 -1
View File
@@ -79,7 +79,7 @@ func TestServerApp_DevMode(t *testing.T) {
waitForHTTPServerStart(port)
providers := app.restSrv.Authenticator.Providers()
require.Equal(t, 10+1, len(providers), "extra auth provider")
require.Equal(t, 11+1, len(providers), "extra auth provider")
assert.Equal(t, "dev", providers[len(providers)-2].Name(), "dev auth provider")
// send ping
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/api/v1/ping", port))
@@ -807,6 +807,7 @@ func prepServerApp(t *testing.T, fn func(o ServerCommand) ServerCommand) (*serve
cmd.Auth.Microsoft.CSEC, cmd.Auth.Microsoft.CID = "csec", "cid"
cmd.Auth.Twitter.CSEC, cmd.Auth.Twitter.CID = "csec", "cid"
cmd.Auth.Patreon.CSEC, cmd.Auth.Patreon.CID = "csec", "cid"
cmd.Auth.Discord.CSEC, cmd.Auth.Discord.CID = "csec", "cid"
cmd.Auth.Telegram = true
cmd.Telegram.Token = "token"
cmd.Auth.Email.Enable = true
+1 -1
View File
@@ -13,7 +13,7 @@ require (
github.com/go-chi/chi/v5 v5.1.0
github.com/go-chi/cors v1.2.1
github.com/go-chi/render v1.0.3
github.com/go-pkgz/auth v1.24.2
github.com/go-pkgz/auth v1.24.3-0.20241007090635-78537e6f812d
github.com/go-pkgz/jrpc v0.3.0
github.com/go-pkgz/lcw/v2 v2.0.0
github.com/go-pkgz/lgr v0.11.1
+2 -2
View File
@@ -60,8 +60,8 @@ github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
github.com/go-oauth2/oauth2/v4 v4.5.2 h1:CuZhD3lhGuI6aNLyUbRHXsgG2RwGRBOuCBfd4WQKqBQ=
github.com/go-oauth2/oauth2/v4 v4.5.2/go.mod h1:wk/2uLImWIa9VVQDgxz99H2GDbhmfi/9/Xr+GvkSUSQ=
github.com/go-pkgz/auth v1.24.2 h1:imMjUvTM0c8iOvP/GNGcuNcB/7gF3jFTF9dIPzlAOqI=
github.com/go-pkgz/auth v1.24.2/go.mod h1:xmnzq6g8mhemW1nHnkuByXkBXsHrNf9/qkiVwJugWIs=
github.com/go-pkgz/auth v1.24.3-0.20241007090635-78537e6f812d h1:6iwosbIwyRm7k0lprEv5mFWpGg1qQKLWJNHL088+Bcs=
github.com/go-pkgz/auth v1.24.3-0.20241007090635-78537e6f812d/go.mod h1:xmnzq6g8mhemW1nHnkuByXkBXsHrNf9/qkiVwJugWIs=
github.com/go-pkgz/email v0.5.0 h1:fdtMDGJ8NwyBACLR0LYHaCIK/OeUwZHMhH7Q0+oty9U=
github.com/go-pkgz/email v0.5.0/go.mod h1:BdxglsQnymzhfdbnncEE72a6DrucZHy6I+42LK2jLEc=
github.com/go-pkgz/expirable-cache v0.1.0/go.mod h1:GTrEl0X+q0mPNqN6dtcQXksACnzCBQ5k/k1SwXJsZKs=
+10 -3
View File
@@ -1,7 +1,7 @@
# auth - authentication via oauth2, direct and email
[![Build Status](https://github.com/go-pkgz/auth/workflows/build/badge.svg)](https://github.com/go-pkgz/auth/actions) [![Coverage Status](https://coveralls.io/repos/github/go-pkgz/auth/badge.svg?branch=master)](https://coveralls.io/github/go-pkgz/auth?branch=master) [![godoc](https://godoc.org/github.com/go-pkgz/auth?status.svg)](https://pkg.go.dev/github.com/go-pkgz/auth?tab=doc)
This library provides "social login" with Github, Google, Facebook, Microsoft, Twitter, Yandex, Battle.net, Apple, Patreon and Telegram as well as custom auth providers and email verification.
This library provides "social login" with Github, Google, Facebook, Microsoft, Twitter, Yandex, Battle.net, Apple, Patreon, Discord and Telegram as well as custom auth providers and email verification.
- Multiple oauth2 providers can be used at the same time
- Special `dev` provider allows local testing and development
@@ -144,7 +144,7 @@ In addition to oauth2 providers `auth.Service` allows to use direct user-defined
```go
service.AddDirectProvider("local", provider.CredCheckerFunc(func(user, password string) (ok bool, err error) {
ok, err := checkUserSomehow(user, password)
ok, err = checkUserSomehow(user, password)
return ok, err
}))
```
@@ -205,7 +205,7 @@ used as `Sender`.
The API for this provider:
- `GET /auth/<name>/login?user=<user>&address=<adsress>&aud=<site_id>&from=<url>` - send confirmation request to user
- `GET /auth/<name>/login?user=<user>&address=<address>&aud=<site_id>&from=<url>` - send confirmation request to user
- `GET /auth/<name>/login?token=<conf.token>&sess=[1|0]` - authorize with confirmation token
The provider acts like any other, i.e. will be registered as `/auth/email/login`.
@@ -604,6 +604,13 @@ For more details refer to [Complete Guide of Battle.net OAuth API and Login Butt
1. Under **"Redirect URIs"** enter the correct url constructed as domain + `/auth/patreon/callback`. ie `https://example.mysite.com/auth/patreon/callback`
1. Take note of the **Client ID** and **Client Secret**
#### Discord Auth Provider ####
1. Log into Discord Developer Portal https://discord.com/developers/applications
2. Click on **New Application** to create the application required for Oauth
3. After filling **"NAME"**, navigate to **"OAuth2"** option on the left sidebar
4. Under **"Redirects"** enter the correct url constructed as domain + `/auth/discord/callback`. ie `https://remark42.mysite.com/auth/discord/callback`
5. Take note of the **CLIENT ID** and **CLIENT SECRET**
#### Twitter Auth Provider
1. Create a new twitter application https://developer.twitter.com/en/apps
1. Fill **App name** and **Description** and **URL** of your site
+2
View File
@@ -257,6 +257,8 @@ func (s *Service) addProviderByName(name string, p provider.Params) {
prov = provider.NewTwitter(p)
case "patreon":
prov = provider.NewPatreon(p)
case "discord":
prov = provider.NewDiscord(p)
case "dev":
prov = provider.NewDev(p)
default:
+26
View File
@@ -265,3 +265,29 @@ func NewPatreon(p Params) Oauth2Handler {
},
})
}
// NewDiscord makes discord oauth2 provider
func NewDiscord(p Params) Oauth2Handler {
return initOauth2Handler(p, Oauth2Handler{
name: "discord",
// see https://discord.com/developers/docs/topics/oauth2
endpoint: oauth2.Endpoint{
AuthURL: "https://discord.com/oauth2/authorize",
TokenURL: "https://discord.com/api/oauth2/token",
},
infoURL: "https://discord.com/api/v10/users/@me",
scopes: []string{"identify"},
mapUser: func(data UserData, _ []byte) token.User {
userInfo := token.User{
ID: "discord_" + token.HashID(sha1.New(), data.Value("id")),
Name: data.Value("username"),
Picture: fmt.Sprintf("https://cdn.discordapp.com/avatars/%s/%s.webp", data.Value("id"), data.Value("avatar")),
}
for k, v := range p.UserAttributes {
userInfo.SetStrAttr(v, data.Value(k))
}
return userInfo
},
})
}
+1 -1
View File
@@ -65,7 +65,7 @@ github.com/go-chi/render
github.com/go-oauth2/oauth2/v4
github.com/go-oauth2/oauth2/v4/errors
github.com/go-oauth2/oauth2/v4/server
# github.com/go-pkgz/auth v1.24.2
# github.com/go-pkgz/auth v1.24.3-0.20241007090635-78537e6f812d
## explicit; go 1.21
github.com/go-pkgz/auth
github.com/go-pkgz/auth/avatar
+2
View File
@@ -68,5 +68,7 @@ services:
- AUTH_FACEBOOK_CSEC=1111
- AUTH_PATREON_CID=1111
- AUTH_PATREON_CSEC=1111
- AUTH_DISCORD_CID=1111
- AUTH_DISCORD_CSEC=1111
volumes:
- ./var:/srv/var
@@ -0,0 +1 @@
<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127.14 96.36"><path fill="#5865f2" d="M107.7,8.07A105.15,105.15,0,0,0,81.47,0a72.06,72.06,0,0,0-3.36,6.83A97.68,97.68,0,0,0,49,6.83,72.37,72.37,0,0,0,45.64,0,105.89,105.89,0,0,0,19.39,8.09C2.79,32.65-1.71,56.6.54,80.21h0A105.73,105.73,0,0,0,32.71,96.36,77.7,77.7,0,0,0,39.6,85.25a68.42,68.42,0,0,1-10.85-5.18c.91-.66,1.8-1.34,2.66-2a75.57,75.57,0,0,0,64.32,0c.87.71,1.76,1.39,2.66,2a68.68,68.68,0,0,1-10.87,5.19,77,77,0,0,0,6.89,11.1A105.25,105.25,0,0,0,126.6,80.22h0C129.24,52.84,122.09,29.11,107.7,8.07ZM42.45,65.69C36.18,65.69,31,60,31,53s5-12.74,11.43-12.74S54,46,53.89,53,48.84,65.69,42.45,65.69Zm42.24,0C78.41,65.69,73.25,60,73.25,53s5-12.74,11.44-12.74S96.23,46,96.12,53,91.08,65.69,84.69,65.69Z"/></svg>

After

Width:  |  Height:  |  Size: 787 B

@@ -99,6 +99,7 @@ export type OAuthProvider =
| 'github'
| 'microsoft'
| 'patreon'
| 'discord'
| 'telegram'
| 'dev';
export type FormProvider = 'email' | 'anonymous';
@@ -9,6 +9,7 @@ export const OAUTH_DATA = {
facebook: require('assets/social/facebook.svg').default as string,
twitter: require('assets/social/twitter.svg').default as string,
patreon: require('assets/social/patreon.svg').default as string,
discord: require('assets/social/discord.svg').default as string,
google: require('assets/social/google.svg').default as string,
microsoft: require('assets/social/microsoft.svg').default as string,
yandex: require('assets/social/yandex.svg').default as string,
+1
View File
@@ -25,6 +25,7 @@ export type OAuthProvider =
| 'github'
| 'microsoft'
| 'patreon'
| 'discord'
| 'telegram'
| 'dev'
export type FormProvider = 'email' | 'anonymous'
@@ -105,6 +105,13 @@ For more details refer to [Yandex OAuth](https://yandex.com/dev/oauth/doc/dg/con
3. In the field **Redirect URIs** enter the correct URI constructed as domain + `/auth/patreon/callback`, i.e., `https://example.mysite.com/auth/patreon/callback`
4. Expand client details and note the **Client ID** and **Client Secret**. Those will be used as `AUTH_PATREON_CID` and `AUTH_PATREON_CSEC`
### Discord Auth Provider
1. Click on **New Application** to create Oauth client https://discord.com/developers/applications
2. After filling **"NAME"**, navigate to **"OAuth2"** option on the left sidebar
3. Under **"Redirects"** enter the correct url constructed as domain + `/auth/discord/callback`. ie `https://remark42.mysite.com/auth/discord/callback`
4. Take note of the **CLIENT ID** and **CLIENT SECRET**, as they are values for `AUTH_DISCORD_CID` and `AUTH_DISCORD_CSEC` respectively
### Telegram
1. Contact [@BotFather](https://t.me/botfather) and follow his instructions to create your bot (call it, for example, "My site auth bot")
@@ -95,6 +95,8 @@ services:
| auth.github.csec | AUTH_GITHUB_CSEC | | GitHub OAuth client secret |
| auth.patreon.cid | AUTH_PATREON_CID | | Patreon OAuth Client ID |
| auth.patreon.csec | AUTH_PATREON_CSEC | | Patreon OAuth Client Secret |
| auth.discord.cid | AUTH_DISCORD_CID | | Discord OAuth Client ID |
| auth.discord.csec | AUTH_DISCORD_CSEC | | Discord OAuth Client Secret |
| auth.telegram | AUTH_TELEGRAM | `false` | Enable Telegram auth (telegram.token must be present) |
| auth.yandex.cid | AUTH_YANDEX_CID | | Yandex OAuth client ID |
| auth.yandex.csec | AUTH_YANDEX_CSEC | | Yandex OAuth client secret |