mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-23 01:20:11 +00:00
Fixed flaw with jellyfin_login; store refresh token in cookies
with jellyfin_login enabled, the username and password vals in the User struct would be "". If you disabled 'required' on the login form, blank username and password would allow you in.
This commit is contained in:
parent
d144077e62
commit
ee3b421566
10
api.go
10
api.go
@ -610,7 +610,15 @@ func (app *appContext) ModifyConfig(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (app *appContext) Logout(gc *gin.Context) {
|
func (app *appContext) Logout(gc *gin.Context) {
|
||||||
app.invalidIds = append(app.invalidIds, gc.GetString("userId"))
|
cookie, err := gc.Cookie("refresh")
|
||||||
|
if err != nil {
|
||||||
|
app.debug.Printf("Couldn't get cookies: %s", err)
|
||||||
|
respond(500, "Couldn't fetch cookies", gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
app.invalidTokens = append(app.invalidTokens, cookie)
|
||||||
|
fmt.Println("After appending", cookie, ":", app.invalidTokens)
|
||||||
|
gc.SetCookie("refresh", "invalid", -1, "/", gc.Request.URL.Hostname(), true, true)
|
||||||
gc.JSON(200, map[string]bool{"success": true})
|
gc.JSON(200, map[string]bool{"success": true})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
26
auth.go
26
auth.go
@ -87,18 +87,30 @@ func (app *appContext) GetToken(gc *gin.Context) {
|
|||||||
var userId, jfId string
|
var userId, jfId string
|
||||||
for _, user := range app.users {
|
for _, user := range app.users {
|
||||||
if user.Username == creds[0] && user.Password == creds[1] {
|
if user.Username == creds[0] && user.Password == creds[1] {
|
||||||
|
if creds[0] != "" && creds[1] != "" {
|
||||||
match = true
|
match = true
|
||||||
|
app.debug.Println("Found existing user")
|
||||||
userId = user.UserID
|
userId = user.UserID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if !match {
|
if !match {
|
||||||
if !app.jellyfinLogin {
|
if !app.jellyfinLogin {
|
||||||
app.info.Println("Auth failed: Invalid username and/or password")
|
app.info.Println("Auth failed: Invalid username and/or password")
|
||||||
respond(401, "Unauthorized", gc)
|
respond(401, "Unauthorized", gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if creds[1] == "" {
|
cookie, err := gc.Cookie("refresh")
|
||||||
token, err := jwt.Parse(creds[0], func(token *jwt.Token) (interface{}, error) {
|
if err == nil && cookie != "" && creds[0] == "" && creds[1] == "" {
|
||||||
|
fmt.Println("Checking:", cookie)
|
||||||
|
for _, token := range app.invalidTokens {
|
||||||
|
if cookie == token {
|
||||||
|
app.debug.Printf("Auth denied: Refresh token in blocklist")
|
||||||
|
respond(401, "Unauthorized", gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
token, err := jwt.Parse(cookie, func(token *jwt.Token) (interface{}, error) {
|
||||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||||
app.debug.Printf("Invalid JWT signing method %s", token.Header["alg"])
|
app.debug.Printf("Invalid JWT signing method %s", token.Header["alg"])
|
||||||
return nil, fmt.Errorf("Unexpected signing method %v", token.Header["alg"])
|
return nil, fmt.Errorf("Unexpected signing method %v", token.Header["alg"])
|
||||||
@ -111,13 +123,6 @@ func (app *appContext) GetToken(gc *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
claims, ok := token.Claims.(jwt.MapClaims)
|
claims, ok := token.Claims.(jwt.MapClaims)
|
||||||
for _, id := range app.invalidIds {
|
|
||||||
if claims["id"].(string) == id {
|
|
||||||
app.debug.Printf("Auth denied: Refresh token in blocklist")
|
|
||||||
respond(401, "Unauthorized", gc)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expiryUnix, err := strconv.ParseInt(claims["exp"].(string), 10, 64)
|
expiryUnix, err := strconv.ParseInt(claims["exp"].(string), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
app.debug.Printf("Auth denied: %s", err)
|
app.debug.Printf("Auth denied: %s", err)
|
||||||
@ -168,7 +173,8 @@ func (app *appContext) GetToken(gc *gin.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
respond(500, "Error generating token", gc)
|
respond(500, "Error generating token", gc)
|
||||||
}
|
}
|
||||||
resp := map[string]string{"token": token, "refresh": refresh}
|
resp := map[string]string{"token": token}
|
||||||
|
gc.SetCookie("refresh", refresh, (3600 * 24), "/", gc.Request.URL.Hostname(), true, true)
|
||||||
gc.JSON(200, resp)
|
gc.JSON(200, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,7 +531,7 @@ document.getElementById('inviteForm').onsubmit = function() {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
function tryLogin(username, password, modal, button) {
|
function tryLogin(username, password, modal, button, callback) {
|
||||||
let req = new XMLHttpRequest();
|
let req = new XMLHttpRequest();
|
||||||
req.responseType = 'json';
|
req.responseType = 'json';
|
||||||
req.onreadystatechange = function() {
|
req.onreadystatechange = function() {
|
||||||
@ -561,7 +561,6 @@ function tryLogin(username, password, modal, button) {
|
|||||||
} else {
|
} else {
|
||||||
const data = this.response;
|
const data = this.response;
|
||||||
window.token = data['token'];
|
window.token = data['token'];
|
||||||
document.cookie = "refresh=" + data['refresh'];
|
|
||||||
generateInvites();
|
generateInvites();
|
||||||
const interval = setInterval(function() { generateInvites(); }, 60 * 1000);
|
const interval = setInterval(function() { generateInvites(); }, 60 * 1000);
|
||||||
let day = document.getElementById('days');
|
let day = document.getElementById('days');
|
||||||
@ -579,6 +578,9 @@ function tryLogin(username, password, modal, button) {
|
|||||||
}
|
}
|
||||||
document.getElementById('logoutButton').setAttribute('style', '');
|
document.getElementById('logoutButton').setAttribute('style', '');
|
||||||
}
|
}
|
||||||
|
if (typeof callback === "function") {
|
||||||
|
callback(this.status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
req.open("GET", "/getToken", true);
|
req.open("GET", "/getToken", true);
|
||||||
@ -600,7 +602,7 @@ document.getElementById('loginForm').onsubmit = function() {
|
|||||||
button.innerHTML =
|
button.innerHTML =
|
||||||
'<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" style="margin-right: 0.5rem;"></span>' +
|
'<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" style="margin-right: 0.5rem;"></span>' +
|
||||||
'Loading...';
|
'Loading...';
|
||||||
tryLogin(details['username'], details['password'], true, button)
|
tryLogin(username = details['username'], password = details['password'], modal = true, button = button)
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -807,12 +809,12 @@ document.getElementById('openUsers').onclick = function () {
|
|||||||
|
|
||||||
generateInvites(empty = true);
|
generateInvites(empty = true);
|
||||||
|
|
||||||
let refreshToken = getCookie("refresh")
|
tryLogin("", "", false, callback = function(code){
|
||||||
if (refreshToken != "") {
|
console.log(code);
|
||||||
tryLogin(refreshToken, "", false)
|
if (code != 200) {
|
||||||
} else {
|
|
||||||
loginModal.show();
|
loginModal.show();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
document.getElementById('logoutButton').onclick = function () {
|
document.getElementById('logoutButton').onclick = function () {
|
||||||
let req = new XMLHttpRequest();
|
let req = new XMLHttpRequest();
|
||||||
@ -822,7 +824,6 @@ document.getElementById('logoutButton').onclick = function () {
|
|||||||
req.onreadystatechange = function() {
|
req.onreadystatechange = function() {
|
||||||
if (this.readyState == 4 && this.status == 200) {
|
if (this.readyState == 4 && this.status == 200) {
|
||||||
window.token = '';
|
window.token = '';
|
||||||
document.cookie = 'refresh=;';
|
|
||||||
location.reload();
|
location.reload();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
4
main.go
4
main.go
@ -42,7 +42,7 @@ type appContext struct {
|
|||||||
bsVersion int
|
bsVersion int
|
||||||
jellyfinLogin bool
|
jellyfinLogin bool
|
||||||
users []User
|
users []User
|
||||||
invalidIds []string
|
invalidTokens []string
|
||||||
jf Jellyfin
|
jf Jellyfin
|
||||||
authJf Jellyfin
|
authJf Jellyfin
|
||||||
datePattern string
|
datePattern string
|
||||||
@ -329,7 +329,7 @@ func main() {
|
|||||||
router.Use(static.Serve("/invite/", static.LocalFile(filepath.Join(app.local_path, "static"), false)))
|
router.Use(static.Serve("/invite/", static.LocalFile(filepath.Join(app.local_path, "static"), false)))
|
||||||
router.GET("/invite/:invCode", app.InviteProxy)
|
router.GET("/invite/:invCode", app.InviteProxy)
|
||||||
api := router.Group("/", app.webAuth())
|
api := router.Group("/", app.webAuth())
|
||||||
api.POST("/logout", app.Logout)
|
router.POST("/logout", app.Logout)
|
||||||
api.POST("/generateInvite", app.GenerateInvite)
|
api.POST("/generateInvite", app.GenerateInvite)
|
||||||
api.GET("/getInvites", app.GetInvites)
|
api.GET("/getInvites", app.GetInvites)
|
||||||
api.POST("/setNotify", app.SetNotify)
|
api.POST("/setNotify", app.SetNotify)
|
||||||
|
Loading…
Reference in New Issue
Block a user