First part of httpOnly JWT cookie implementation

This commit is contained in:
Florian Sylvain
2023-01-12 00:04:26 +01:00
parent a09ae668ce
commit 200efe0e90
4 changed files with 43 additions and 20 deletions
+15 -6
View File
@@ -10,10 +10,12 @@ import (
"github.com/joho/godotenv" "github.com/joho/godotenv"
) )
var ginMode string var (
var apiPort string ginMode string
var frontPort string apiPort string
var hostAddress string frontPort string
hostAddress string
)
func initEnvVariables() { func initEnvVariables() {
if godotenv.Load() != nil { if godotenv.Load() != nil {
@@ -50,6 +52,12 @@ func corsMiddleware(c *gin.Context) {
c.Next() c.Next()
} }
func jwtProxyMiddleware(c *gin.Context) {
jwtToken, _ := c.Cookie("jwt")
c.Request.Header.Set("Authorization", fmt.Sprintf("Bearer %v", jwtToken))
c.Next()
}
func initArticlesRoutes(r *gin.Engine) { func initArticlesRoutes(r *gin.Engine) {
articlesRouter := r.Group("/articles") articlesRouter := r.Group("/articles")
articlesRouter.Use(corsMiddleware, api.AuthMiddleware.MiddlewareFunc()) articlesRouter.Use(corsMiddleware, api.AuthMiddleware.MiddlewareFunc())
@@ -63,10 +71,11 @@ func initArticlesRoutes(r *gin.Engine) {
func initGin() { func initGin() {
r := gin.Default() r := gin.Default()
r.Use(corsMiddleware) r.Use(jwtProxyMiddleware, corsMiddleware)
if ginMode == "release" { if ginMode == "release" {
gin.SetMode(ginMode) gin.SetMode(ginMode)
api.AuthMiddleware.SecureCookie = true
} }
initBasicRoutes(r) initBasicRoutes(r)
@@ -77,6 +86,6 @@ func initGin() {
func main() { func main() {
initEnvVariables() initEnvVariables()
initJWT()
initGin() initGin()
initJWT()
} }
+13
View File
@@ -2,6 +2,7 @@ package api
import ( import (
"errors" "errors"
"net/http"
"os" "os"
"time" "time"
@@ -21,11 +22,23 @@ var UsersLocation = database.Location{Database: "gohcms", Collection: "users"}
var AuthMiddleware, _ = jwt.New(&jwt.GinJWTMiddleware{ var AuthMiddleware, _ = jwt.New(&jwt.GinJWTMiddleware{
Realm: "GohCMS", Realm: "GohCMS",
Key: []byte(os.Getenv("APP_JWT_SECRET")), Key: []byte(os.Getenv("APP_JWT_SECRET")),
SendCookie: true,
CookieHTTPOnly: true,
CookieSameSite: http.SameSiteStrictMode,
Timeout: time.Hour, Timeout: time.Hour,
MaxRefresh: time.Hour, MaxRefresh: time.Hour,
LoginResponse: JWTLoginResponse,
Authenticator: JWTAuthenticator, Authenticator: JWTAuthenticator,
}) })
func JWTLoginResponse(c *gin.Context, code int, message string, expire time.Time) {
if code == http.StatusOK {
c.JSON(code, gin.H{"code": code, "message": "Successfully logged in!", "expire": expire.Format(time.RFC3339)})
} else {
c.JSON(code, gin.H{"code": code, "message": "Something wrong has happened."})
}
}
func JWTAuthenticator(c *gin.Context) (interface{}, error) { func JWTAuthenticator(c *gin.Context) (interface{}, error) {
var user = User{} var user = User{}
err := c.BindJSON(&user) err := c.BindJSON(&user)
+2 -2
View File
@@ -15,8 +15,8 @@ const baseURL = `http://${__APP_ENV__.APP_HOST_ADDRESS}:${__APP_ENV__.APP_API_PO
export async function getArticles(id: string) : Promise<Array<Article>> { export async function getArticles(id: string) : Promise<Array<Article>> {
return await fetch(`${baseURL}/articles/${id}`, { return await fetch(`${baseURL}/articles/${id}`, {
credentials: 'include',
method: 'GET', method: 'GET',
headers: { "Authorization": `Bearer ${useAuthStore().token}` }
}) })
.then(result => result.json()) .then(result => result.json())
.catch(error => { .catch(error => {
@@ -26,8 +26,8 @@ export async function getArticles(id: string) : Promise<Array<Article>> {
export async function postArticle(article: Article) : Promise<object> { export async function postArticle(article: Article) : Promise<object> {
return await fetch(`${baseURL}/articles/${article.titleID}`, { return await fetch(`${baseURL}/articles/${article.titleID}`, {
credentials: 'include',
method: 'POST', method: 'POST',
headers: { "Authorization": `Bearer ${useAuthStore().token}` },
body: JSON.stringify(article) body: JSON.stringify(article)
}) })
.then(result => result.json()) .then(result => result.json())
+7 -6
View File
@@ -19,11 +19,11 @@ function updateJWTcookies(JWTdata: jwtFormat): void {
const cookieExpire = new Date(JWTdata.expire) const cookieExpire = new Date(JWTdata.expire)
cookieExpire.setDate(cookieExpire.getDate() + 1) cookieExpire.setDate(cookieExpire.getDate() + 1)
setCookie({ // setCookie({
key: 'JWTtoken', // key: 'JWTtoken',
value: JWTdata.token, // value: JWTdata.token,
expire: cookieExpire.toString() // expire: cookieExpire.toString()
}) // })
setCookie({ setCookie({
key: 'JWTexpire', key: 'JWTexpire',
value: JWTdata.expire, value: JWTdata.expire,
@@ -43,7 +43,7 @@ function jwtHandler(apiResponse: jwtFormat): void {
} }
updateJWTcookies(apiResponse) updateJWTcookies(apiResponse)
disableErrors() disableErrors()
authStore.token = apiResponse.token authStore.token = 'pouet'
authStore.expire = apiResponse.expire authStore.expire = apiResponse.expire
isTokenOK.value = true isTokenOK.value = true
} }
@@ -51,6 +51,7 @@ function jwtHandler(apiResponse: jwtFormat): void {
function login(email: string, password: string): void { function login(email: string, password: string): void {
fetch(`http://${__APP_ENV__.APP_HOST_ADDRESS}:${__APP_ENV__.APP_API_PORT}/login/`, { fetch(`http://${__APP_ENV__.APP_HOST_ADDRESS}:${__APP_ENV__.APP_API_PORT}/login/`, {
method: "POST", method: "POST",
credentials: 'include',
body: JSON.stringify({ body: JSON.stringify({
email: email, email: email,
password: password password: password