Skip to content

Commit

Permalink
feat(jwt): add nonce and only allow one session
Browse files Browse the repository at this point in the history
  • Loading branch information
Darkness4 committed Dec 5, 2023
1 parent baa2123 commit 91a563a
Show file tree
Hide file tree
Showing 13 changed files with 171 additions and 110 deletions.
35 changes: 22 additions & 13 deletions cmd/dpsproxy-server/components/GenerateRoute.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
{{define "GenerateRoute"}}
<div>
<button
id="generate"
_="on click call login(false) then set #response.innerHTML to it then set the *display of #response to 'block'"
<form
id="generate-route"
_="on submit halt the event
call login(event)
set #response.innerHTML to it
set the *display of #response to 'block'"
>
<div>
<input type="checkbox" name="generate" />
<label for="remember">Generate new route.</label>
</div>
<small>Generating a new route will remove the old one.</small>
<div>
<input type="checkbox" name="remember" />
<label for="remember">Long-lived token.</label>
</div>
<small
>Do not share the long-lived token. A third party could re-use this token to
hijack the route. Fetching a new route will delete old tokens. Generated
token and established connections persist after the token is expired.</small
>
Generate Route
</button>
<button
id="retrieve"
_="on click call login(true) then set #response.innerHTML to it then set the *display of #response to 'block'"
>
Retrieve Route
</button>
</div>
<input type="submit" value="Fetch route" />
</form>
{{ end }}
12 changes: 6 additions & 6 deletions cmd/dpsproxy-server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,13 +265,13 @@ var app = &cli.App{
})

// Backend
jwt := jwt.Service{
Secret: []byte(jwtSecret),
Nonces: nonces,
}
r.Post(
"/routes",
handler.GenerateRoute(publicDomain, routes, authService, jwt.Secret(jwtSecret)),
)
r.Get(
"/routes",
handler.RetrieveRoute(publicDomain, routes, jwt.Secret(jwtSecret)),
handler.GenerateRoute(publicDomain, routes, authService, jwt),
)

// Pages rendering
Expand Down Expand Up @@ -327,7 +327,7 @@ var app = &cli.App{
server := proxyssh.NewServer(
sshListenAddress,
&config,
jwt.Secret(jwtSecret),
jwt,
routes,
publicDomain,
anonymous,
Expand Down
9 changes: 6 additions & 3 deletions cmd/dpsproxy-server/pages/page.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@
}

/**
* @param {bool} retrieve - Retrieve route instead of generating it.
* @param {FormDataEvent} event
* @returns {Promise<string>}
*/
async function login(retrieve) {
async function login(event) {
if (typeof window.ethereum === 'undefined') {
alert('Metamask not detected');
}
const formData = new FormData(event.target);
const params = new URLSearchParams(formData);
try {
// Fetch account
const accounts = await window.ethereum.request({
Expand All @@ -70,7 +72,7 @@
data: Array.from(challengeBytes),
sig: Array.from(hexStringToBytes(sig)),
};
resp = await fetch(`/routes?retrieve=${retrieve}`, {
resp = await fetch(`/routes?${params.toString()}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Expand Down Expand Up @@ -98,6 +100,7 @@
{{ .RouteCount }} route{{ if gt .RouteCount 1 }}s{{ end }}
allocated.
</h3>
<h3>Only one route per user.</h3>
</hgroup>
</header>

Expand Down
3 changes: 2 additions & 1 deletion database/migrations/000001_create_tables.up.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ PRAGMA foreign_keys = ON;
BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS nonces (
nonce VARCHAR(255) NOT NULL PRIMARY KEY,
expiration TIMESTAMP NOT NULL
expiration TIMESTAMP NOT NULL,
ref VARCHAR(255) -- A nonce can be associated with something.
);

CREATE TABLE IF NOT EXISTS routes (
Expand Down
2 changes: 2 additions & 0 deletions database/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 53 additions & 6 deletions database/nonce/nonce.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ import (
"database/sql"
"encoding/base64"
"errors"
"fmt"
"time"

"github.com/deepsquare-io/proxy/database"
)

const expirationDuration = 10 * time.Minute

const nonceLength = 16 // You can adjust the length as needed

func generateNonce() (string, error) {
Expand All @@ -31,10 +30,40 @@ func generateNonce() (string, error) {
return nonceString, nil
}

type GenerateOption func(*GenerateOptions)

type GenerateOptions struct {
expiration time.Duration
ref string
}

func applyGenerateOptions(opts []GenerateOption) *GenerateOptions {
o := &GenerateOptions{
expiration: 10 * time.Minute,
}
for _, opt := range opts {
opt(o)
}
return o
}

func WithExpiration(expiration time.Duration) GenerateOption {
return func(o *GenerateOptions) {
o.expiration = expiration
}
}

func WithRef(ref string) GenerateOption {
return func(o *GenerateOptions) {
o.ref = ref
}
}

// Repository defines the nonce methods.
type Repository interface {
Generate(ctx context.Context) (string, error)
Generate(ctx context.Context, opts ...GenerateOption) (string, error)
IsValid(ctx context.Context, nonce string) (bool, error)
ClearByRef(ctx context.Context, ref string) error
}

// NewRepository wraps around a SQL database to execute the nonce methods.
Expand All @@ -48,18 +77,25 @@ type repository struct {
*database.Queries
}

func (r *repository) Generate(ctx context.Context) (string, error) {
func (r *repository) Generate(ctx context.Context, opts ...GenerateOption) (string, error) {
o := applyGenerateOptions(opts)
nonce, err := generateNonce()
if err != nil {
panic(err)
}
if err := r.set(ctx, nonce, time.Now().Add(expirationDuration)); err != nil {
if err := r.set(ctx, nonce, time.Now().Add(o.expiration), o.ref); err != nil {
return "", err
}
return nonce, nil
}

func (r *repository) set(ctx context.Context, value string, expiration time.Time) (err error) {
func (r *repository) set(
ctx context.Context,
value string,
expiration time.Time,
ref string,
) (err error) {
fmt.Printf("value=%s ref=%s\n", value, ref)
_, err = r.Queries.UpdateNonce(ctx, database.UpdateNonceParams{
Nonce: value,
Expiration: expiration,
Expand All @@ -71,6 +107,10 @@ func (r *repository) set(ctx context.Context, value string, expiration time.Time
return r.Queries.CreateNonce(ctx, database.CreateNonceParams{
Nonce: value,
Expiration: expiration,
Ref: sql.NullString{
String: ref,
Valid: ref != "",
},
})
}
return err
Expand All @@ -89,3 +129,10 @@ func (r *repository) IsValid(ctx context.Context, existing string) (bool, error)
}
return true, nil
}

func (r *repository) ClearByRef(ctx context.Context, ref string) error {
return r.Queries.DeleteNoncesByRef(ctx, sql.NullString{
String: ref,
Valid: true,
})
}
5 changes: 4 additions & 1 deletion database/queries.sql
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
-- name: GetNonce :one
SELECT * FROM nonces WHERE nonce = ? AND expiration > ? LIMIT 1;

-- name: DeleteNoncesByRef :exec
DELETE FROM nonces WHERE ref = ?;

-- name: CreateNonce :exec
INSERT INTO nonces (nonce, expiration) VALUES (?, ?);
INSERT INTO nonces (nonce, expiration, ref) VALUES (?, ?, ?);

-- name: UpdateNonce :one
UPDATE nonces SET expiration = ? WHERE nonce = ? RETURNING nonce;
Expand Down
19 changes: 15 additions & 4 deletions database/queries.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ require (
github.com/go-chi/chi/v5 v5.0.10
github.com/golang-jwt/jwt/v5 v5.2.0
github.com/golang-migrate/migrate/v4 v4.16.2
github.com/google/uuid v1.4.0
github.com/gorilla/csrf v1.7.2
github.com/joho/godotenv v1.5.1
github.com/lithammer/shortuuid/v4 v4.0.0
github.com/rs/zerolog v1.31.0
github.com/sqlc-dev/sqlc v1.23.0
github.com/urfave/cli/v2 v2.26.0
Expand Down Expand Up @@ -105,7 +105,6 @@ require (
github.com/google/go-github/v39 v39.2.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/s2a-go v0.1.4 // indirect
github.com/google/uuid v1.4.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
github.com/googleapis/gax-go/v2 v2.11.0 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
Expand Down
7 changes: 0 additions & 7 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,6 @@ github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.1.0 h1:UGKbA/IPjtS6zLcdB7i5TyACMgSbOTiR8qzXgw8HWQU=
github.com/golang-jwt/jwt/v5 v5.1.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-migrate/migrate/v4 v4.16.2 h1:8coYbMKUyInrFk1lfGfRovTLAW7PhWp8qQDT2iKfuoA=
Expand Down Expand Up @@ -523,8 +521,6 @@ github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lithammer/shortuuid/v4 v4.0.0 h1:QRbbVkfgNippHOS8PXDkti4NaWeyYfcBTHtw7k08o4c=
github.com/lithammer/shortuuid/v4 v4.0.0/go.mod h1:Zs8puNcrvf2rV9rTH51ZLLcj7ZXqQI3lv67aw4KiB1Y=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
Expand Down Expand Up @@ -636,7 +632,6 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
Expand Down Expand Up @@ -705,8 +700,6 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/urfave/cli/v2 v2.26.0 h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI=
github.com/urfave/cli/v2 v2.26.0/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/xanzy/go-gitlab v0.15.0 h1:rWtwKTgEnXyNUGrOArN7yyc3THRkpYcKXIXia9abywQ=
Expand Down
Loading

0 comments on commit 91a563a

Please sign in to comment.