OK I think I got it working by digging in nakama code.
How do get the encryption_key
from the config? It seems I’m only able to access env vars that are under runtime.env
package handlers
import (
"ac/errors"
"context"
"crypto"
"database/sql"
"fmt"
"time"
"github.com/gofrs/uuid/v5"
jwt "github.com/golang-jwt/jwt/v4"
"github.com/heroiclabs/nakama-common/runtime"
)
// Photon Documentation:
// https://doc.photonengine.com/fusion/current/manual/connection-and-matchmaking/authentication/custom-authentication
func RPC_PhotonAuthenticate(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) {
// Get the auth token from the query parameters
var authToken string
queryParams := ctx.Value(runtime.RUNTIME_CTX_QUERY_PARAMS).(map[string][]string)
value, ok := queryParams["auth_token"]
if !ok || len(value) == 0 {
return "{\"ResultCode\": 3, \"Message\": \"Invalid parameters\"}", nil
}
authToken = value[0]
// env := ctx.Value(runtime.RUNTIME_CTX_ENV).(map[string]string)
encryptionKey := "defaultencryptionkey" //env["encryption_key"] (DONT HARDCODE)
encryptionKeyByte := []byte(encryptionKey)
userID, _, _, _, _, ok := parseToken(encryptionKeyByte, authToken)
if !ok {
return "{\"ResultCode\": 2, \"Message\": \"Invalid token\"}", nil
}
return fmt.Sprintf("{\"ResultCode\": 1, \"UserId\": \"%s\"}", userID), nil
}
// From: https://github.com/heroiclabs/nakama/blob/master/server/api_authenticate.go
type SessionTokenClaims struct {
TokenId string `json:"tid,omitempty"`
UserId string `json:"uid,omitempty"`
Username string `json:"usn,omitempty"`
Vars map[string]string `json:"vrs,omitempty"`
ExpiresAt int64 `json:"exp,omitempty"`
}
func (stc *SessionTokenClaims) Valid() error {
// Verify expiry.
if stc.ExpiresAt <= time.Now().UTC().Unix() {
vErr := new(jwt.ValidationError)
vErr.Inner = errors.New("Token is expired")
vErr.Errors |= jwt.ValidationErrorExpired
return vErr
}
return nil
}
// From: https://github.com/heroiclabs/nakama/blob/master/server/api.go
func parseToken(hmacSecretByte []byte, tokenString string) (userID uuid.UUID, username string, vars map[string]string, exp int64, tokenId string, ok bool) {
jwtToken, err := jwt.ParseWithClaims(tokenString, &SessionTokenClaims{}, func(token *jwt.Token) (interface{}, error) {
if s, ok := token.Method.(*jwt.SigningMethodHMAC); !ok || s.Hash != crypto.SHA256 {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return hmacSecretByte, nil
})
if err != nil {
return
}
claims, ok := jwtToken.Claims.(*SessionTokenClaims)
if !ok || !jwtToken.Valid {
return
}
userID, err = uuid.FromString(claims.UserId)
if err != nil {
return
}
return userID, claims.Username, claims.Vars, claims.ExpiresAt, claims.TokenId, true
}