The refreshtoken no longer cares about when a token expired. When they want a new jtw from refresh a new refresh token is made also
This commit is contained in:
parent
b02ed3f86a
commit
e7f706b6e7
@ -15,7 +15,6 @@ type RefreshTokenEntity struct {
|
|||||||
Id int64
|
Id int64
|
||||||
Username string
|
Username string
|
||||||
Token string
|
Token string
|
||||||
ExpiresAt time.Time
|
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
LastUpdated time.Time
|
LastUpdated time.Time
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ CREATE TABLE RefreshTokens (
|
|||||||
ID INTEGER PRIMARY KEY AUTOINCREMENT,
|
ID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
Username TEXT NOT NULL,
|
Username TEXT NOT NULL,
|
||||||
Token TEXT NOT NULL,
|
Token TEXT NOT NULL,
|
||||||
ExpiresAt DATETIME NOT NULL,
|
|
||||||
CreatedAt DATETIME NOT NULL,
|
CreatedAt DATETIME NOT NULL,
|
||||||
LastUpdated DATETIME NOT NULL
|
LastUpdated DATETIME NOT NULL
|
||||||
)
|
)
|
||||||
|
@ -15,7 +15,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type RefreshTokenTable interface {
|
type RefreshTokenTable interface {
|
||||||
Create(username string, token string, expiresAt time.Time) (int64, error)
|
Create(username string, token string) (int64, error)
|
||||||
GetByUsername(name string) (domain.RefreshTokenEntity, error)
|
GetByUsername(name string) (domain.RefreshTokenEntity, error)
|
||||||
DeleteById(id int64) (int64, error)
|
DeleteById(id int64) (int64, error)
|
||||||
}
|
}
|
||||||
@ -30,12 +30,12 @@ func NewRefreshTokenRepository(conn *sql.DB) RefreshTokenRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt RefreshTokenRepository) Create(username string, token string, expiresAt time.Time) (int64, error) {
|
func (rt RefreshTokenRepository) Create(username string, token string) (int64, error) {
|
||||||
dt := time.Now()
|
dt := time.Now()
|
||||||
builder := sqlbuilder.NewInsertBuilder()
|
builder := sqlbuilder.NewInsertBuilder()
|
||||||
builder.InsertInto(refreshTokenTableName)
|
builder.InsertInto(refreshTokenTableName)
|
||||||
builder.Cols("Username", "Token", "ExpiresAt", "CreatedAt", "LastUpdated")
|
builder.Cols("Username", "Token", "CreatedAt", "LastUpdated")
|
||||||
builder.Values(username, token, expiresAt, dt, dt)
|
builder.Values(username, token, dt, dt)
|
||||||
query, args := builder.Build()
|
query, args := builder.Build()
|
||||||
|
|
||||||
_, err := rt.connection.Exec(query, args...)
|
_, err := rt.connection.Exec(query, args...)
|
||||||
@ -89,11 +89,10 @@ func (rd RefreshTokenRepository) processRows(rows *sql.Rows) []domain.RefreshTok
|
|||||||
var id int64
|
var id int64
|
||||||
var username string
|
var username string
|
||||||
var token string
|
var token string
|
||||||
var expiresAt time.Time
|
|
||||||
var createdAt time.Time
|
var createdAt time.Time
|
||||||
var lastUpdated time.Time
|
var lastUpdated time.Time
|
||||||
|
|
||||||
err := rows.Scan(&id, &username, &token, &expiresAt, &createdAt, &lastUpdated)
|
err := rows.Scan(&id, &username, &token, &createdAt, &lastUpdated)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
@ -102,7 +101,6 @@ func (rd RefreshTokenRepository) processRows(rows *sql.Rows) []domain.RefreshTok
|
|||||||
Id: id,
|
Id: id,
|
||||||
Username: username,
|
Username: username,
|
||||||
Token: token,
|
Token: token,
|
||||||
ExpiresAt: expiresAt,
|
|
||||||
CreatedAt: createdAt,
|
CreatedAt: createdAt,
|
||||||
LastUpdated: lastUpdated,
|
LastUpdated: lastUpdated,
|
||||||
})
|
})
|
||||||
|
@ -3,7 +3,6 @@ package repositories_test
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.jamestombleson.com/jtom38/go-cook/internal/repositories"
|
"git.jamestombleson.com/jtom38/go-cook/internal/repositories"
|
||||||
_ "github.com/glebarez/go-sqlite"
|
_ "github.com/glebarez/go-sqlite"
|
||||||
@ -18,7 +17,7 @@ func TestRefreshTokenCreate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
client := repositories.NewRefreshTokenRepository(conn)
|
client := repositories.NewRefreshTokenRepository(conn)
|
||||||
rows, err := client.Create("tester", "BadTokenDontUse", time.Now().Add(time.Hour+1))
|
rows, err := client.Create("tester", "BadTokenDontUse")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Log(err)
|
t.Log(err)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
@ -37,7 +36,7 @@ func TestRefreshTokenGetByUsername(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
client := repositories.NewRefreshTokenRepository(conn)
|
client := repositories.NewRefreshTokenRepository(conn)
|
||||||
rows, err := client.Create("tester", "BadTokenDoNotUse", time.Now().Add(time.Hour+1))
|
rows, err := client.Create("tester", "BadTokenDoNotUse")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Log(err)
|
t.Log(err)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
@ -68,7 +67,7 @@ func TestRefreshTokenDeleteById(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
client := repositories.NewRefreshTokenRepository(conn)
|
client := repositories.NewRefreshTokenRepository(conn)
|
||||||
_, err = client.Create("tester", "BadTokenDoNotUse", time.Now().Add(time.Hour+1))
|
_, err = client.Create("tester", "BadTokenDoNotUse")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Log(err)
|
t.Log(err)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
|
@ -3,20 +3,25 @@ package services
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.jamestombleson.com/jtom38/go-cook/internal/domain"
|
"git.jamestombleson.com/jtom38/go-cook/internal/domain"
|
||||||
"git.jamestombleson.com/jtom38/go-cook/internal/repositories"
|
"git.jamestombleson.com/jtom38/go-cook/internal/repositories"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ErrUnexpectedAmountOfRowsUpdated = "got a unexpected of rows updated"
|
||||||
|
)
|
||||||
|
|
||||||
type RefreshToken interface {
|
type RefreshToken interface {
|
||||||
Create(username string, expiresAt time.Time) (string, error)
|
Create(username string) (string, error)
|
||||||
GetByName(name string) (domain.RefreshTokenEntity, error)
|
GetByName(name string) (domain.RefreshTokenEntity, error)
|
||||||
Delete(id int64) (int64, error)
|
Delete(id int64) (int64, error)
|
||||||
IsRequestValid(username, refreshToken string, jwtExpiresAt time.Time) error
|
IsRequestValid(username, refreshToken string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A new jwt token can be made if the user has the correct refresh token for the user.
|
||||||
|
// It will also require the old JWT token so the expire time is pulled and part of the validation
|
||||||
type RefreshTokenService struct {
|
type RefreshTokenService struct {
|
||||||
table repositories.RefreshTokenTable
|
table repositories.RefreshTokenTable
|
||||||
}
|
}
|
||||||
@ -27,13 +32,26 @@ func NewRefreshTokenService(conn *sql.DB) RefreshTokenService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt RefreshTokenService) Create(username string, expiresAt time.Time) (string, error) {
|
func (rt RefreshTokenService) Create(username string) (string, error) {
|
||||||
|
//if a refresh token already exists for a user, reuse
|
||||||
|
existingToken, err := rt.GetByName(username)
|
||||||
|
if err == nil {
|
||||||
|
rowsRemoved, err := rt.Delete(existingToken.Id)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if rowsRemoved != 1 {
|
||||||
|
return "", errors.New(ErrUnexpectedAmountOfRowsUpdated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
token, err := uuid.NewV7()
|
token, err := uuid.NewV7()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
rows, err := rt.table.Create(username, token.String(), expiresAt)
|
rows, err := rt.table.Create(username, token.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -54,19 +72,15 @@ func (rt RefreshTokenService) Delete(id int64) (int64, error) {
|
|||||||
return rt.table.DeleteById(id)
|
return rt.table.DeleteById(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt RefreshTokenService) IsRequestValid(username, refreshToken string, jwtExpiresAt time.Time) error {
|
func (rt RefreshTokenService) IsRequestValid(username, refreshToken string) error {
|
||||||
token, err := rt.GetByName(username)
|
token, err := rt.GetByName(username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.Token != refreshToken) {
|
if token.Token != refreshToken {
|
||||||
return errors.New("the refresh token given does not match")
|
return errors.New("the refresh token given does not match")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.ExpiresAt != jwtExpiresAt) {
|
|
||||||
return errors.New("the time when the jwt token expires does not match what was given")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user