mirror of
https://github.com/mjl-/mox.git
synced 2024-12-26 00:13:47 +03:00
webmail: rename query string param "token" to "singleUseToken" to be less scary in access logs
these singleusetokens can be redeemed once. so when you see it in the logs, it can't be used again. they are short-lived anyway. this change should help prevent me periodically investigating token handling...
This commit is contained in:
parent
a977082b89
commit
594182aae5
10 changed files with 35 additions and 29 deletions
|
@ -130,9 +130,10 @@ func (w Webmail) Logout(ctx context.Context) {
|
|||
xcheckf(ctx, err, "logout")
|
||||
}
|
||||
|
||||
// Token returns a token to use for an SSE connection. A token can only be used for
|
||||
// a single SSE connection. Tokens are stored in memory for a maximum of 1 minute,
|
||||
// with at most 10 unused tokens (the most recently created) per account.
|
||||
// Token returns a single-use token to use for an SSE connection. A token can only
|
||||
// be used for a single SSE connection. Tokens are stored in memory for a maximum
|
||||
// of 1 minute, with at most 10 unused tokens (the most recently created) per
|
||||
// account.
|
||||
func (Webmail) Token(ctx context.Context) string {
|
||||
reqInfo := ctx.Value(requestInfoCtxKey).(requestInfo)
|
||||
return sseTokens.xgenerate(ctx, reqInfo.Account.Name, reqInfo.LoginAddress, reqInfo.SessionToken)
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
},
|
||||
{
|
||||
"Name": "Token",
|
||||
"Docs": "Token returns a token to use for an SSE connection. A token can only be used for\na single SSE connection. Tokens are stored in memory for a maximum of 1 minute,\nwith at most 10 unused tokens (the most recently created) per account.",
|
||||
"Docs": "Token returns a single-use token to use for an SSE connection. A token can only\nbe used for a single SSE connection. Tokens are stored in memory for a maximum\nof 1 minute, with at most 10 unused tokens (the most recently created) per\naccount.",
|
||||
"Params": [],
|
||||
"Returns": [
|
||||
{
|
||||
|
|
|
@ -750,9 +750,10 @@ export class Client {
|
|||
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params) as void
|
||||
}
|
||||
|
||||
// Token returns a token to use for an SSE connection. A token can only be used for
|
||||
// a single SSE connection. Tokens are stored in memory for a maximum of 1 minute,
|
||||
// with at most 10 unused tokens (the most recently created) per account.
|
||||
// Token returns a single-use token to use for an SSE connection. A token can only
|
||||
// be used for a single SSE connection. Tokens are stored in memory for a maximum
|
||||
// of 1 minute, with at most 10 unused tokens (the most recently created) per
|
||||
// account.
|
||||
async Token(): Promise<string> {
|
||||
const fn: string = "Token"
|
||||
const paramTypes: string[][] = []
|
||||
|
|
|
@ -448,9 +448,10 @@ var api;
|
|||
const params = [];
|
||||
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||
}
|
||||
// Token returns a token to use for an SSE connection. A token can only be used for
|
||||
// a single SSE connection. Tokens are stored in memory for a maximum of 1 minute,
|
||||
// with at most 10 unused tokens (the most recently created) per account.
|
||||
// Token returns a single-use token to use for an SSE connection. A token can only
|
||||
// be used for a single SSE connection. Tokens are stored in memory for a maximum
|
||||
// of 1 minute, with at most 10 unused tokens (the most recently created) per
|
||||
// account.
|
||||
async Token() {
|
||||
const fn = "Token";
|
||||
const paramTypes = [];
|
||||
|
|
|
@ -448,9 +448,10 @@ var api;
|
|||
const params = [];
|
||||
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||
}
|
||||
// Token returns a token to use for an SSE connection. A token can only be used for
|
||||
// a single SSE connection. Tokens are stored in memory for a maximum of 1 minute,
|
||||
// with at most 10 unused tokens (the most recently created) per account.
|
||||
// Token returns a single-use token to use for an SSE connection. A token can only
|
||||
// be used for a single SSE connection. Tokens are stored in memory for a maximum
|
||||
// of 1 minute, with at most 10 unused tokens (the most recently created) per
|
||||
// account.
|
||||
async Token() {
|
||||
const fn = "Token";
|
||||
const paramTypes = [];
|
||||
|
|
|
@ -489,7 +489,8 @@ type ioErr struct {
|
|||
}
|
||||
|
||||
// serveEvents serves an SSE connection. Authentication is done through a query
|
||||
// string parameter "token", a one-time-use token returned by the Token API call.
|
||||
// string parameter "singleUseToken", a one-time-use token returned by the Token
|
||||
// API call.
|
||||
func serveEvents(ctx context.Context, log mlog.Log, accountPath string, w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "GET" {
|
||||
http.Error(w, "405 - method not allowed - use get", http.StatusMethodNotAllowed)
|
||||
|
@ -504,7 +505,7 @@ func serveEvents(ctx context.Context, log mlog.Log, accountPath string, w http.R
|
|||
}
|
||||
|
||||
q := r.URL.Query()
|
||||
token := q.Get("token")
|
||||
token := q.Get("singleUseToken")
|
||||
if token == "" {
|
||||
http.Error(w, "400 - bad request - missing credentials", http.StatusBadRequest)
|
||||
return
|
||||
|
|
|
@ -131,13 +131,13 @@ func TestView(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
testFail("POST", eventsURL+"?token="+tokens[0]+"&request="+string(requestJSON), http.StatusMethodNotAllowed) // Must be GET.
|
||||
testFail("GET", eventsURL, http.StatusBadRequest) // Missing token.
|
||||
testFail("GET", eventsURL+"?token="+tokens[0]+"&request="+string(requestJSON), http.StatusBadRequest) // Bad (old) token.
|
||||
testFail("GET", eventsURL+"?token="+tokens[len(tokens)-5]+"&request=bad", http.StatusBadRequest) // Bad request.
|
||||
testFail("POST", eventsURL+"?singleUseToken="+tokens[0]+"&request="+string(requestJSON), http.StatusMethodNotAllowed) // Must be GET.
|
||||
testFail("GET", eventsURL, http.StatusBadRequest) // Missing token.
|
||||
testFail("GET", eventsURL+"?singleUseToken="+tokens[0]+"&request="+string(requestJSON), http.StatusBadRequest) // Bad (old) token.
|
||||
testFail("GET", eventsURL+"?singleUseToken="+tokens[len(tokens)-5]+"&request=bad", http.StatusBadRequest) // Bad request.
|
||||
|
||||
// Start connection for testing and filters below.
|
||||
req, err := http.NewRequest("GET", eventsURL+"?token="+tokens[len(tokens)-1]+"&request="+string(requestJSON), nil)
|
||||
req, err := http.NewRequest("GET", eventsURL+"?singleUseToken="+tokens[len(tokens)-1]+"&request="+string(requestJSON), nil)
|
||||
tcheck(t, err, "making request")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
tcheck(t, err, "http transaction")
|
||||
|
@ -168,7 +168,7 @@ func TestView(t *testing.T) {
|
|||
}
|
||||
|
||||
// Can only use a token once.
|
||||
testFail("GET", eventsURL+"?token="+tokens[len(tokens)-1]+"&request=bad", http.StatusBadRequest)
|
||||
testFail("GET", eventsURL+"?singleUseToken="+tokens[len(tokens)-1]+"&request=bad", http.StatusBadRequest)
|
||||
|
||||
// Check a few initial query/page combinations.
|
||||
testConn := func(token, more string, request Request, check func(EventStart, eventReader)) {
|
||||
|
@ -176,7 +176,7 @@ func TestView(t *testing.T) {
|
|||
|
||||
reqJSON, err := json.Marshal(request)
|
||||
tcheck(t, err, "marshal request json")
|
||||
req, err := http.NewRequest("GET", eventsURL+"?token="+token+more+"&request="+string(reqJSON), nil)
|
||||
req, err := http.NewRequest("GET", eventsURL+"?singleUseToken="+token+more+"&request="+string(reqJSON), nil)
|
||||
tcheck(t, err, "making request")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
tcheck(t, err, "http transaction")
|
||||
|
|
|
@ -194,8 +194,8 @@ func handle(apiHandler http.Handler, isForwarded bool, accountPath string, w htt
|
|||
log := pkglog.WithContext(ctx).With(slog.String("userauth", ""))
|
||||
|
||||
// Server-sent event connection, for all initial data (list of mailboxes), list of
|
||||
// messages, and all events afterwards. Authenticated through a token in the query
|
||||
// string, which it got from a Token API call.
|
||||
// messages, and all events afterwards. Authenticated through a single use token in
|
||||
// the query string, which it got from a Token API call.
|
||||
if r.URL.Path == "/events" {
|
||||
serveEvents(ctx, log, accountPath, w, r)
|
||||
return
|
||||
|
|
|
@ -448,9 +448,10 @@ var api;
|
|||
const params = [];
|
||||
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||
}
|
||||
// Token returns a token to use for an SSE connection. A token can only be used for
|
||||
// a single SSE connection. Tokens are stored in memory for a maximum of 1 minute,
|
||||
// with at most 10 unused tokens (the most recently created) per account.
|
||||
// Token returns a single-use token to use for an SSE connection. A token can only
|
||||
// be used for a single SSE connection. Tokens are stored in memory for a maximum
|
||||
// of 1 minute, with at most 10 unused tokens (the most recently created) per
|
||||
// account.
|
||||
async Token() {
|
||||
const fn = "Token";
|
||||
const paramTypes = [];
|
||||
|
@ -6911,7 +6912,7 @@ const init = async () => {
|
|||
}
|
||||
}
|
||||
catch (err) { }
|
||||
eventSource = new window.EventSource('events?token=' + encodeURIComponent(token) + '&request=' + encodeURIComponent(JSON.stringify(request)) + slow);
|
||||
eventSource = new window.EventSource('events?singleUseToken=' + encodeURIComponent(token) + '&request=' + encodeURIComponent(JSON.stringify(request)) + slow);
|
||||
let eventID = window.setTimeout(() => dom._kids(statusElem, 'Connecting... '), 1000);
|
||||
eventSource.addEventListener('open', (e) => {
|
||||
log('eventsource open', { e });
|
||||
|
|
|
@ -7208,7 +7208,7 @@ const init = async () => {
|
|||
}
|
||||
} catch (err) {}
|
||||
|
||||
eventSource = new window.EventSource('events?token=' + encodeURIComponent(token)+'&request='+encodeURIComponent(JSON.stringify(request))+slow)
|
||||
eventSource = new window.EventSource('events?singleUseToken=' + encodeURIComponent(token)+'&request='+encodeURIComponent(JSON.stringify(request))+slow)
|
||||
let eventID = window.setTimeout(() => dom._kids(statusElem, 'Connecting... '), 1000)
|
||||
eventSource.addEventListener('open', (e: Event) => {
|
||||
log('eventsource open', {e})
|
||||
|
|
Loading…
Reference in a new issue