user authentication structure in place

This commit is contained in:
zomo
2026-01-05 23:10:00 -06:00
parent 9770ef9f21
commit 5c6e93c7e4
9 changed files with 261 additions and 112 deletions

View File

@@ -1,10 +1,12 @@
package api
import (
"log"
"net/http"
"net/url"
"github.com/gin-gonic/gin"
"zomo.dev/largehadroncollider/ttv"
)
func (server *ApiServer) loadEndpoints() {
@@ -18,9 +20,9 @@ func (server *ApiServer) loadEndpoints() {
serverInfo := ServerInfo{
ClientID: server.conf.ClientID,
AuthParams: TwitchAuthParams{
ClientID: server.conf.ClientID,
ForceVerify: false,
RedirectURI: server.conf.RedirectURI,
ClientID: server.conf.ClientID,
ForceVerify: false,
RedirectURI: server.conf.RedirectURI,
ResponseType: "code",
Scope: []string{
"bits:read",
@@ -51,46 +53,62 @@ func (server *ApiServer) loadEndpoints() {
server.engine.GET("/auth", func(c *gin.Context) {
q := c.Request.URL.Query()
if resp := loadAuthQueryOk(q); resp != nil {
if reqBody := loadAuthQueryOk(q); reqBody != nil {
// ok
// TODO check state (need state system)
// TODO POST https://id.twitch.tv/oauth2/token - returns TwitchAuthTokenResp
// convert expiresIn to time.Time (minus like 15 minutes as a buffer period)
// UpdateUserAuth()
// TODO return twitch ok (or err if can't POST)
} else if resp := loadAuthQueryErr(q); resp != nil {
// TODO check state value (need state system)
authResp, err := server.twitch.Auth.DoAuth(server.conf, reqBody.Code)
if err != nil {
log.Println("Error Authenticating:")
log.Printf(" Parsed Request Body: %+v", reqBody)
log.Printf(" Authorization Error: %v", err)
c.AbortWithStatus(http.StatusInternalServerError)
return
}
err = server.twitch.Auth.UpdateUserDetails(server.db, authResp.AccessToken, authResp.RefreshToken, authResp.ExpiresIn)
if err != nil {
log.Println("Error Updating User Details:")
log.Printf(" Parsed Request Body: %+v", reqBody)
log.Printf(" Authorization Response: %+v", authResp)
log.Printf(" Error: %v", err)
c.AbortWithStatus(http.StatusInternalServerError)
return
}
// TODO return twitch ok
c.Status(http.StatusOK)
} else if reqBody := loadAuthQueryErr(q); reqBody != nil {
// err from twitch
// TODO check state (need state system)
// TODO return twitch err
c.AbortWithStatus(http.StatusBadRequest)
} else {
// err in params
// TODO return param err
c.AbortWithStatus(http.StatusBadRequest)
}
// TODO auth response from twitch
// parse args as TwitchAuthRespOk or TwitchAuthRespErr
// verify state with db and client id with config
c.JSON(http.StatusOK, serverInfo)
})
}
type ServerInfo struct {
ClientID string `json:"client_id"`
ClientID string `json:"client_id"`
AuthParams TwitchAuthParams `json:"auth_params"`
}
type TwitchAuthParams struct {
ClientID string `json:"client_id"`
ForceVerify bool `json:"force_verify"`
RedirectURI string `json:"redirect_uri"`
ResponseType string `json:"response_type"`
Scope []string `json:"scope"`
State string `json:"state"`
ClientID string `json:"client_id"`
ForceVerify bool `json:"force_verify"`
RedirectURI string `json:"redirect_uri"`
ResponseType string `json:"response_type"`
Scope []string `json:"scope"`
State string `json:"state"`
}
func loadAuthQueryOk(query url.Values) *TwitchAuthRespOk {
func loadAuthQueryOk(query url.Values) *ttv.TwitchAuthRespOk {
if query.Has("code") && query.Has("scope") && query.Has("state") {
return &TwitchAuthRespOk{
return &ttv.TwitchAuthRespOk{
Code: query.Get("code"),
Scope: query.Get("scope"),
State: query.Get("state"),
@@ -99,9 +117,9 @@ func loadAuthQueryOk(query url.Values) *TwitchAuthRespOk {
return nil
}
func loadAuthQueryErr(query url.Values) *TwitchAuthRespErr {
func loadAuthQueryErr(query url.Values) *ttv.TwitchAuthRespErr {
if query.Has("error") && query.Has("error_description") && query.Has("state") {
return &TwitchAuthRespErr{
return &ttv.TwitchAuthRespErr{
Err: query.Get("error"),
ErrDesc: query.Get("error_description"),
State: query.Get("state"),
@@ -109,23 +127,3 @@ func loadAuthQueryErr(query url.Values) *TwitchAuthRespErr {
}
return nil
}
type TwitchAuthRespOk struct {
Code string `json:"code"`
Scope string `json:"scope"`
State string `json:"state"`
}
type TwitchAuthRespErr struct {
Err string `json:"error"`
ErrDesc string `json:"error_description"`
State string `json:"state"`
}
type TwitchAuthTokenResp struct {
AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"`
RefreshToken string `json:"refresh_token"`
Scope []string `json:"scope"`
TokenType string `json:"token_type"`
}

View File

@@ -10,17 +10,17 @@ import (
func InitApiServer(conf *util.Config, dbConn *db.DBConn, twitchConn *ttv.TwitchConn) (*ApiServer, error) {
engine := gin.Default()
apiServer := &ApiServer{ engine, conf, dbConn, twitchConn }
apiServer := &ApiServer{engine, conf, dbConn, twitchConn}
apiServer.loadEndpoints()
return apiServer, nil
}
type ApiServer struct {
engine *gin.Engine
conf *util.Config
db *db.DBConn
conf *util.Config
db *db.DBConn
twitch *ttv.TwitchConn
}