Skip to content

Commit

Permalink
feat: try to glue this linking style
Browse files Browse the repository at this point in the history
  • Loading branch information
Gusted committed May 25, 2021
1 parent 6954cc1 commit ed0bcb7
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 4 deletions.
23 changes: 19 additions & 4 deletions handlers/oauth_provider/access_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,14 @@ func AccessTokenPost(c *fiber.Ctx) error {
}

claims := token.Claims.(jwt.MapClaims)

state, userID := claims["state"].(string), uint(claims["userID"].(float64))

styleID, ok := claims["styleID"].(string)
if !ok {
styleID = ""
}

if stateQuery != state {
return errorMessage(c, 500, "State doesn't match.")
}
Expand All @@ -57,10 +63,19 @@ func AccessTokenPost(c *fiber.Ctx) error {
return errorMessage(c, 500, "Couldn't find the user that was specified, please notify the admins.")
}

jwt, err := utils.NewJWTToken().
SetClaim("scopes", strings.Join(OAuth.Scopes, ",")).
SetClaim("userID", user.ID).
GetSignedString(utils.OAuthPSigningKey)
var jwt string

if styleID != "" {
jwt, err = utils.NewJWTToken().
SetClaim("styleID", styleID).
SetClaim("userID", user.ID).
GetSignedString(utils.OAuthPSigningKey)
} else {
jwt, err = utils.NewJWTToken().
SetClaim("scopes", strings.Join(OAuth.Scopes, ",")).
SetClaim("userID", user.ID).
GetSignedString(utils.OAuthPSigningKey)
}

if err != nil {
return errorMessage(c, 500, "Couldn't create access_token please notify the admins.")
Expand Down
112 changes: 112 additions & 0 deletions handlers/oauth_provider/authorize_style.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package oauth_provider

import (
"fmt"
"time"

"github.com/form3tech-oss/jwt-go"
"github.com/gofiber/fiber/v2"
"userstyles.world/database"
jwtware "userstyles.world/handlers/jwt"
"userstyles.world/models"
"userstyles.world/utils"
)

func AuthorizeStyleGet(c *fiber.Ctx) error {
u, _ := jwtware.User(c)

// Under no circumstance this page should be loaded in some third-party frame.
// It should be fully the user's consent to choose to authorize.
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
c.Response().Header.Set("X-Frame-Options", "DENY")

clientID, state := c.Query("client_id"), c.Query("state")
if clientID == "" {
return errorMessage(c, 400, "No client_id specified")
}
OAuth, err := models.GetOAuthByClientID(database.DB, clientID)
if err != nil || OAuth.ID == 0 {
return errorMessage(c, 400, "Incorrect client_id specified")
}

// User has to authorize within 2 hours.
// To migate any weird attack we include the ID of the user that wishes to authorize.
// Such that this key cannot be replaced by some other user.
// And to follow our weird state-less design we include the state.
// Thus not storing the state.
jwt, err := utils.NewJWTToken().
SetClaim("state", state).
SetClaim("userID", u.ID).
SetExpiration(time.Now().Add(time.Hour * 2)).
GetSignedString(utils.OAuthPSigningKey)

if err != nil {
fmt.Println("Error: Couldn't make a JWT Token due to:", err.Error())
return errorMessage(c, 500, "Couldn't make JWT Token, please notify the admins.")
}

arguments := fiber.Map{
"User": u,
"OAuth": OAuth,
"SecureToken": utils.PrepareText(jwt, utils.AEAD_OAUTHP),
}
for _, v := range OAuth.Scopes {
arguments["Scope_"+v] = true
}

return c.Render("authorize_style", arguments)
}

func AuthorizeStylePost(c *fiber.Ctx) error {
u, _ := jwtware.User(c)
styleID, oauthID, secureToken := c.Query("styleID"), c.Query("oauthID"), c.Query("token")

OAuth, err := models.GetOAuthByID(database.DB, oauthID)
if err != nil || OAuth.ID == 0 {
return errorMessage(c, 400, "Incorrect oauthID specified")
}

unsealedText, err := utils.DecodePreparedText(secureToken, utils.AEAD_OAUTHP)
if err != nil {
fmt.Println("Error: Couldn't unseal JWT Token:", err.Error())
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}

token, err := jwt.Parse(unsealedText, utils.OAuthPJwtKeyFunction)
if err != nil || !token.Valid {
fmt.Println("Error: Couldn't unseal JWT Token:", err.Error())
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}
claims := token.Claims.(jwt.MapClaims)

userID, ok := claims["userID"].(float64)
if !ok || userID != float64(u.ID) {
fmt.Println("WARNING!: Invalid userID")
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}

state, ok := claims["state"].(string)
if !ok {
fmt.Println("WARNING!: Invalid state")
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}

jwt, err := utils.NewJWTToken().
SetClaim("state", state).
SetClaim("userID", u.ID).
SetClaim("styleID", styleID).
SetExpiration(time.Now().Add(time.Minute * 10)).
GetSignedString(utils.OAuthPSigningKey)

if err != nil {
fmt.Println("Error: Couldn't create JWT Token:", err.Error())
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}

returnCode := "?code=" + utils.PrepareText(jwt, utils.AEAD_OAUTHP)
if state != "" {
returnCode += "&state=" + state
}

return c.Redirect(OAuth.RedirectURI + "/" + returnCode)
}
31 changes: 31 additions & 0 deletions views/authorize_style.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en">
<head>
{{ template "partials/head" . }}
</head>
<body>
{{ template "partials/nav" . }}

<main>
<div class="wrapper py:l">
{{ template "partials/alert" . }}

<section class="styles mt:l">
<h2 class="sub-title td:d">Userstyles</h2>
{{ if ne (len .Styles) 0 }}
<p class="description">Please pick an existing style or a new style, that you'd like to link.</p>
<div class="grid flex rwrap mx:r mt:m">
{{ range .Styles }}
{{ template "partials/link_style" . }}
{{ end }}
</div>
{{ else }}
{{ template "partials/new_style" }}
{{ end }}
</section>
</div>
</main>

{{ template "partials/footer" . }}
</body>
</html>
9 changes: 9 additions & 0 deletions views/partials/link_style.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{{- $method := printf "oauth/authorize_style?styleID=%d&token=%s&oauthID=%d" .ID .SecureToken .OAuth.ID -}}
<a class="card col gap animate bd:o" href="{{ $method }}">
<div class="thumbnail">
{{ template "partials/preview_image" . }}
</div>
<div class="flex cwrap px:m bd:t fg:1 py:m">
<span class="f:h3 f:b my:0">{{- .Name -}}</span>
</div>
</a>
Empty file added views/partials/new_style.html
Empty file.

0 comments on commit ed0bcb7

Please sign in to comment.