From 0480c4a9e61964b096dc01bd82d61667cf072306 Mon Sep 17 00:00:00 2001 From: meskio <meskio@sindominio.net> Date: Tue, 29 Sep 2020 12:30:17 +0200 Subject: [PATCH] Create tokens that don't expire --- api/api.go | 2 +- api/auth.go | 23 ++++++++++++++++------- src/App.js | 17 ++++++++++------- src/SignIn.js | 16 +++++++++++++++- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/api/api.go b/api/api.go index 91d8705..79f2ffe 100644 --- a/api/api.go +++ b/api/api.go @@ -31,7 +31,7 @@ func Init(dbPath string, signKey string, r *mux.Router) error { a := api{db, []byte(signKey)} - token, err := a.newToken(0, "admin") + token, err := a.newToken(0, "admin", false) log.Print(token) r.HandleFunc("/signin", a.SignIn).Methods("POST") diff --git a/api/auth.go b/api/auth.go index 94eba5a..66930ee 100644 --- a/api/auth.go +++ b/api/auth.go @@ -15,6 +15,7 @@ import ( type creds struct { Name string `json:"name"` Password string `json:"password"` + NoExpire bool `json:"noExpire"` } func (a *api) SignIn(w http.ResponseWriter, req *http.Request) { @@ -44,7 +45,7 @@ func (a *api) SignIn(w http.ResponseWriter, req *http.Request) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - token, err := a.newToken(member.Num, member.Role) + token, err := a.newToken(member.Num, member.Role, !c.NoExpire) if err != nil { log.Printf("Can't create a token: %v", err) w.WriteHeader(http.StatusInternalServerError) @@ -80,7 +81,7 @@ func (a *api) GetToken(w http.ResponseWriter, req *http.Request) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - token, err := a.newToken(int(num), role) + token, err := a.newToken(int(num), role, true) if err != nil { log.Printf("Can't create a token: %v", err) w.WriteHeader(http.StatusInternalServerError) @@ -162,12 +163,16 @@ func (a *api) authNumRole(fn func(int, string, http.ResponseWriter, *http.Reques } } -func (a *api) newToken(num int, role string) (string, error) { - token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ +func (a *api) newToken(num int, role string, expire bool) (string, error) { + claims := jwt.MapClaims{ "num": num, "role": role, - "exp": time.Now().Add(time.Hour * 24).Unix(), - }) + } + if expire { + claims["exp"] = time.Now().Add(time.Hour * 24).Unix() + } + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(a.signKey) } @@ -185,7 +190,11 @@ func (a *api) validateToken(token string) (bool, jwt.MapClaims) { if !ok { return false, nil } - exp, ok := claims["exp"].(float64) + expClaim, ok := claims["exp"] + if !ok { + return true, claims + } + exp, ok := expClaim.(float64) if !ok { return false, claims } diff --git a/src/App.js b/src/App.js index 1b9fdea..6a867f8 100644 --- a/src/App.js +++ b/src/App.js @@ -73,10 +73,6 @@ class App extends React.Component { this.storeState(token, member.num, member.role); } - isLoged() { - return this.state.token !== null && !this.tokenExpired(); - } - logout() { this.setState({ num: null, @@ -86,16 +82,23 @@ class App extends React.Component { this.storeState("", "", ""); } - tokenExpired() { + isLoged() { + if (!this.state.token) { + return false; + } + const token = this.state.token; const base64Url = token.split('.')[1]; const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); - const claims = JSON.parse(jsonPayload); - return claims["exp"] < Date.now(); + const claims = JSON.parse(jsonPayload); + if (claims["exp"] === undefined) { + return true; + } + return claims["exp"] < Date.now()/1000; }; render() { diff --git a/src/SignIn.js b/src/SignIn.js index 3efae07..fe4d28b 100644 --- a/src/SignIn.js +++ b/src/SignIn.js @@ -8,6 +8,7 @@ class SignIn extends React.Component { this.state = { name: "", password: "", + noExpire: false, isLoading: false, badAuth: false, error: null @@ -21,7 +22,10 @@ class SignIn extends React.Component { this.setState({isLoading: true, error: null}); const body = JSON.stringify({ - name: this.state.name, password: this.state.password}); + name: this.state.name, + password: this.state.password, + noExpire: this.state.noExpire + }); fetch("/api/signin", {method: "POST", body}) .then(response => { @@ -73,6 +77,16 @@ class SignIn extends React.Component { Nombre o contraseña invalidos. </Form.Control.Feedback> </Form.Group> + + <Form.Group> + <Form.Check + type="switch" + id="noExpire" + label="Permanecer conectada con este navegador" + onChange={e => this.setState({noExpire: e.target.checked}) } + /> + </Form.Group> + <Button variant="primary" type="submit" -- GitLab