mirror of
https://github.com/netbirdio/netbird.git
synced 2025-05-23 09:51:13 +02:00
* shutdown the pkce server on user cancellation * Refactor openURL to exclusively manage authentication flow instructions and browser launching * Refactor authentication flow initialization based on client OS The NewOAuthFlow method now first checks the operating system and if it is a non-desktop Linux, it opts for Device Code Flow. PKCEFlow is tried first and if it fails, then it falls back on Device Code Flow. If both unsuccessful, the authentication process halts and error messages have been updated to provide more helpful feedback for troubleshooting authentication errors * Replace log-based Linux desktop check with process check To verify if a Linux OS is running a desktop environment in the Authentication utility, the log-based method that checks the XDG_CURRENT_DESKTOP env has been replaced with a method that checks directly if either X or Wayland display server processes are running. This method is more reliable as it directly checks for the display server process rather than relying on an environment variable that may not be set in all desktop environments. * Refactor PKCE Authorization Flow to improve server handling * refactor check for linux running desktop environment * Improve server shutdown handling and encapsulate handlers with new server multiplexer The changes enhance the way the server shuts down by specifying a context with timeout of 5 seconds, adding a safeguard to ensure the server halts even on potential hanging requests. Also, the server's root handler is now encapsulated within a new ServeMux instance, to support multiple registrations of a path
69 lines
1.5 KiB
Go
69 lines
1.5 KiB
Go
package auth
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
func randomBytesInHex(count int) (string, error) {
|
|
buf := make([]byte, count)
|
|
_, err := io.ReadFull(rand.Reader, buf)
|
|
if err != nil {
|
|
return "", fmt.Errorf("could not generate %d random bytes: %v", count, err)
|
|
}
|
|
|
|
return hex.EncodeToString(buf), nil
|
|
}
|
|
|
|
// isValidAccessToken is a simple validation of the access token
|
|
func isValidAccessToken(token string, audience string) error {
|
|
if token == "" {
|
|
return fmt.Errorf("token received is empty")
|
|
}
|
|
|
|
encodedClaims := strings.Split(token, ".")[1]
|
|
claimsString, err := base64.RawURLEncoding.DecodeString(encodedClaims)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
claims := Claims{}
|
|
err = json.Unmarshal(claimsString, &claims)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if claims.Audience == nil {
|
|
return fmt.Errorf("required token field audience is absent")
|
|
}
|
|
|
|
// Audience claim of JWT can be a string or an array of strings
|
|
typ := reflect.TypeOf(claims.Audience)
|
|
switch typ.Kind() {
|
|
case reflect.String:
|
|
if claims.Audience == audience {
|
|
return nil
|
|
}
|
|
case reflect.Slice:
|
|
for _, aud := range claims.Audience.([]interface{}) {
|
|
if audience == aud {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
return fmt.Errorf("invalid JWT token audience field")
|
|
}
|
|
|
|
// isLinuxRunningDesktop checks if a Linux OS is running desktop environment
|
|
func isLinuxRunningDesktop() bool {
|
|
return os.Getenv("DESKTOP_SESSION") != "" || os.Getenv("XDG_CURRENT_DESKTOP") != ""
|
|
}
|