sso: expire tokens after usage
This commit is contained in:
parent
fa2ccfe42e
commit
6317b384d9
@ -4,7 +4,7 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func domainSsoNew(domain string) (string, error) {
|
||||
func domainSsoSecretNew(domain string) (string, error) {
|
||||
if domain == "" {
|
||||
return "", errorMissingField
|
||||
}
|
||||
@ -29,7 +29,7 @@ func domainSsoNew(domain string) (string, error) {
|
||||
return ssoSecret, nil
|
||||
}
|
||||
|
||||
func domainSsoNewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
func domainSsoSecretNewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
type request struct {
|
||||
OwnerToken *string `json:"ownerToken"`
|
||||
Domain *string `json:"domain"`
|
||||
@ -59,7 +59,7 @@ func domainSsoNewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
ssoSecret, err := domainSsoNew(domain)
|
||||
ssoSecret, err := domainSsoSecretNew(domain)
|
||||
if err != nil {
|
||||
bodyMarshal(w, response{"success": false, "message": err.Error()})
|
||||
return
|
||||
|
@ -1,5 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type ssoPayload struct {
|
||||
Domain string `json:"domain"`
|
||||
Token string `json:"token"`
|
||||
@ -8,3 +12,50 @@ type ssoPayload struct {
|
||||
Link string `json:"link"`
|
||||
Photo string `json:"photo"`
|
||||
}
|
||||
|
||||
func ssoTokenNew(domain string, commenterToken string) (string, error) {
|
||||
token, err := randomHex(32)
|
||||
if err != nil {
|
||||
logger.Errorf("error generating SSO token hex: %v", err)
|
||||
return "", errorInternal
|
||||
}
|
||||
|
||||
statement := `
|
||||
INSERT INTO
|
||||
ssoTokens (token, domain, commenterToken, creationDate)
|
||||
VALUES ($1, $2, $3, $4 );
|
||||
`
|
||||
_, err = db.Exec(statement, token, domain, commenterToken, time.Now().UTC())
|
||||
if err != nil {
|
||||
logger.Errorf("error inserting SSO token: %v", err)
|
||||
return "", errorInternal
|
||||
}
|
||||
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func ssoTokenExtract(token string) (string, string, error) {
|
||||
statement := `
|
||||
SELECT domain, commenterToken
|
||||
FROM ssoTokens
|
||||
WHERE token = $1;
|
||||
`
|
||||
row := db.QueryRow(statement, token)
|
||||
|
||||
var domain string
|
||||
var commenterToken string
|
||||
if err := row.Scan(&domain, &commenterToken); err != nil {
|
||||
return "", "", errorNoSuchToken
|
||||
}
|
||||
|
||||
statement = `
|
||||
DELETE FROM ssoTokens
|
||||
WHERE token = $1;
|
||||
`
|
||||
if _, err := db.Exec(statement, token); err != nil {
|
||||
logger.Errorf("cannot delete SSO token after usage: %v", err)
|
||||
return "", "", errorInternal
|
||||
}
|
||||
|
||||
return domain, commenterToken, nil
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ func ssoCallbackHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if payload.Domain == "" || payload.Token == "" || payload.Email == "" || payload.Name == "" {
|
||||
if payload.Token == "" || payload.Email == "" || payload.Name == "" {
|
||||
fmt.Fprintf(w, "Error: %s\n", errorMissingField.Error())
|
||||
return
|
||||
}
|
||||
@ -45,7 +45,13 @@ func ssoCallbackHandler(w http.ResponseWriter, r *http.Request) {
|
||||
payload.Photo = "undefined"
|
||||
}
|
||||
|
||||
d, err := domainGet(payload.Domain)
|
||||
domain, commenterToken, err := ssoTokenExtract(payload.Token)
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "Error: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
d, err := domainGet(domain)
|
||||
if err != nil {
|
||||
if err == errorNoSuchDomain {
|
||||
fmt.Fprintf(w, "Error: %s\n", err.Error())
|
||||
@ -76,13 +82,13 @@ func ssoCallbackHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = commenterGetByCommenterToken(payload.Token)
|
||||
_, err = commenterGetByCommenterToken(commenterToken)
|
||||
if err != nil && err != errorNoSuchToken {
|
||||
fmt.Fprintf(w, "Error: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c, err := commenterGetByEmail("sso:"+d.Domain, payload.Email)
|
||||
c, err := commenterGetByEmail("sso:"+domain, payload.Email)
|
||||
if err != nil && err != errorNoSuchCommenter {
|
||||
fmt.Fprintf(w, "Error: %s\n", err.Error())
|
||||
return
|
||||
@ -92,7 +98,7 @@ func ssoCallbackHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// TODO: in case of returning users, update the information we have on record?
|
||||
if err == errorNoSuchCommenter {
|
||||
commenterHex, err = commenterNew(payload.Email, payload.Name, payload.Link, payload.Photo, "sso:"+d.Domain, "")
|
||||
commenterHex, err = commenterNew(payload.Email, payload.Name, payload.Link, payload.Photo, "sso:"+domain, "")
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "Error: %s", err.Error())
|
||||
return
|
||||
@ -101,7 +107,7 @@ func ssoCallbackHandler(w http.ResponseWriter, r *http.Request) {
|
||||
commenterHex = c.CommenterHex
|
||||
}
|
||||
|
||||
if err = commenterSessionUpdate(payload.Token, commenterHex); err != nil {
|
||||
if err = commenterSessionUpdate(commenterToken, commenterHex); err != nil {
|
||||
fmt.Fprintf(w, "Error: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
@ -53,9 +53,15 @@ func ssoRedirectHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
tokenBytes, err := hex.DecodeString(commenterToken)
|
||||
token, err := ssoTokenNew(domain, commenterToken)
|
||||
if err != nil {
|
||||
logger.Errorf("cannot decode hex commenterToken: %v", err)
|
||||
fmt.Fprintf(w, "Error: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
tokenBytes, err := hex.DecodeString(token)
|
||||
if err != nil {
|
||||
logger.Errorf("cannot decode hex token: %v", err)
|
||||
fmt.Fprintf(w, "Error: %s\n", errorInternal.Error())
|
||||
return
|
||||
}
|
||||
@ -74,7 +80,7 @@ func ssoRedirectHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
q := u.Query()
|
||||
q.Set("token", commenterToken)
|
||||
q.Set("token", token)
|
||||
q.Set("hmac", signature)
|
||||
u.RawQuery = q.Encode()
|
||||
|
||||
|
@ -15,7 +15,7 @@ func apiRouterInit(router *mux.Router) error {
|
||||
router.HandleFunc("/api/domain/new", domainNewHandler).Methods("POST")
|
||||
router.HandleFunc("/api/domain/delete", domainDeleteHandler).Methods("POST")
|
||||
router.HandleFunc("/api/domain/clear", domainClearHandler).Methods("POST")
|
||||
router.HandleFunc("/api/domain/sso/new", domainSsoNewHandler).Methods("POST")
|
||||
router.HandleFunc("/api/domain/sso/new", domainSsoSecretNewHandler).Methods("POST")
|
||||
router.HandleFunc("/api/domain/list", domainListHandler).Methods("POST")
|
||||
router.HandleFunc("/api/domain/update", domainUpdateHandler).Methods("POST")
|
||||
router.HandleFunc("/api/domain/moderator/new", domainModeratorNewHandler).Methods("POST")
|
||||
|
6
db/20190420231030-sso-tokens.sql
Normal file
6
db/20190420231030-sso-tokens.sql
Normal file
@ -0,0 +1,6 @@
|
||||
CREATE TABLE IF NOT EXISTS ssoTokens (
|
||||
token TEXT NOT NULL UNIQUE PRIMARY KEY ,
|
||||
domain TEXT NOT NULL ,
|
||||
commenterToken TEXT NOT NULL ,
|
||||
creationDate TIMESTAMP NOT NULL
|
||||
);
|
Loading…
Reference in New Issue
Block a user