Fediverse-based authentication (#1846)
* Able to authenticate user against IndieAuth. For #1273 * WIP server indieauth endpoint. For https://github.com/owncast/owncast/issues/1272 * Add migration to remove access tokens from user * Add authenticated bool to user for display purposes * Add indieauth modal and auth flair to display names. For #1273 * Validate URLs and display errors * Renames, cleanups * Handle relative auth endpoint paths. Add error handling for missing redirects. * Disallow using display names in use by registered users. Closes #1810 * Verify code verifier via code challenge on callback * Use relative path to authorization_endpoint * Post-rebase fixes * Use a timestamp instead of a bool for authenticated * Propertly handle and display error in modal * Use auth'ed timestamp to derive authenticated flag to display in chat * Fediverse chat auth via OTP * Increase validity time just in case * Add fediverse auth into auth modal * Text, validation, cleanup updates for fedi auth * Fix typo * Remove unused images * Remove unused file * Add chat display name to auth modal text
This commit is contained in:
63
auth/fediverse/fediverse.go
Normal file
63
auth/fediverse/fediverse.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package fediverse
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
// OTPRegistration represents a single OTP request.
|
||||
type OTPRegistration struct {
|
||||
UserID string
|
||||
UserDisplayName string
|
||||
Code string
|
||||
Account string
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
// Key by access token to limit one OTP request for a person
|
||||
// to be active at a time.
|
||||
var pendingAuthRequests = make(map[string]OTPRegistration)
|
||||
|
||||
// RegisterFediverseOTP will start the OTP flow for a user, creating a new
|
||||
// code and returning it to be sent to a destination.
|
||||
func RegisterFediverseOTP(accessToken, userID, userDisplayName, account string) OTPRegistration {
|
||||
code, _ := createCode()
|
||||
r := OTPRegistration{
|
||||
Code: code,
|
||||
UserID: userID,
|
||||
UserDisplayName: userDisplayName,
|
||||
Account: account,
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
pendingAuthRequests[accessToken] = r
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// ValidateFediverseOTP will verify a OTP code for a auth request.
|
||||
func ValidateFediverseOTP(accessToken, code string) (bool, *OTPRegistration) {
|
||||
request, ok := pendingAuthRequests[accessToken]
|
||||
|
||||
if !ok || request.Code != code || time.Since(request.Timestamp) > time.Minute*10 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
delete(pendingAuthRequests, accessToken)
|
||||
return true, &request
|
||||
}
|
||||
|
||||
func createCode() (string, error) {
|
||||
table := [...]byte{'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}
|
||||
|
||||
digits := 6
|
||||
b := make([]byte, digits)
|
||||
n, err := io.ReadAtLeast(rand.Reader, b, digits)
|
||||
if n != digits {
|
||||
return "", err
|
||||
}
|
||||
for i := 0; i < len(b); i++ {
|
||||
b[i] = table[int(b[i])%len(table)]
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
Reference in New Issue
Block a user