mirror of https://github.com/jlelse/GoBlog
Update IndieAuth (w/o PKCE for now)
This commit is contained in:
parent
0be61598ef
commit
db1c4901c7
|
@ -56,7 +56,10 @@ func prepareAppDbStatement(query string) (*sql.Stmt, error) {
|
|||
dbStatementCacheMutex.Unlock()
|
||||
return stmt, nil
|
||||
})
|
||||
return stmt.(*sql.Stmt), err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return stmt.(*sql.Stmt), nil
|
||||
}
|
||||
|
||||
func appDbExec(query string, args ...interface{}) (sql.Result, error) {
|
||||
|
|
|
@ -71,6 +71,22 @@ func migrateDb() error {
|
|||
return err
|
||||
},
|
||||
},
|
||||
&migrator.Migration{
|
||||
Name: "00006",
|
||||
Func: func(tx *sql.Tx) error {
|
||||
_, err := tx.Exec(`
|
||||
create table indieauthauthnew (time text not null, code text not null, client text not null, redirect text not null, scope text not null);
|
||||
insert into indieauthauthnew (time, code, client, redirect, scope) select time, code, client, redirect, scope from indieauthauth;
|
||||
drop table indieauthauth;
|
||||
alter table indieauthauthnew rename to indieauthauth;
|
||||
create table indieauthtokennew (time text not null, token text not null, client text not null, scope text not null);
|
||||
insert into indieauthtokennew (time, token, client, scope) select time, token, client, scope from indieauthtoken;
|
||||
drop table indieauthtoken;
|
||||
alter table indieauthtokennew rename to indieauthtoken;
|
||||
`)
|
||||
return err
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
|
|
6
go.mod
6
go.mod
|
@ -39,7 +39,7 @@ require (
|
|||
github.com/pelletier/go-toml v1.8.1 // indirect
|
||||
github.com/smartystreets/assertions v1.2.0 // indirect
|
||||
github.com/snabb/sitemap v1.0.0
|
||||
github.com/spf13/afero v1.5.0 // indirect
|
||||
github.com/spf13/afero v1.5.1 // indirect
|
||||
github.com/spf13/cast v1.3.1
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/viper v1.7.1
|
||||
|
@ -57,12 +57,12 @@ require (
|
|||
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9 // indirect
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect
|
||||
golang.org/x/mod v0.4.0 // indirect
|
||||
golang.org/x/net v0.0.0-20201207224615-747e23833adb // indirect
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 // indirect
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
||||
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d // indirect
|
||||
golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b // indirect
|
||||
golang.org/x/text v0.3.4 // indirect
|
||||
golang.org/x/tools v0.0.0-20201208062317-e652b2f42cc7 // indirect
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
|
|
13
go.sum
13
go.sum
|
@ -287,8 +287,8 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k
|
|||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.5.0 h1:8Wb647pxgVlypPIdcDlffCLCHCElBZ1sCF6i85qNvRw=
|
||||
github.com/spf13/afero v1.5.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/afero v1.5.1 h1:VHu76Lk0LSP1x254maIu2bplkWpfBWI+B+6fdoZprcg=
|
||||
github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
|
||||
|
@ -418,8 +418,8 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201207224615-747e23833adb h1:xj2oMIbduz83x7tzglytWT7spn6rP+9hvKjTpro6/pM=
|
||||
golang.org/x/net v0.0.0-20201207224615-747e23833adb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 h1:lwlPPsmjDKK0J6eG6xDWd5XPehI0R024zxjDnw3esPA=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -460,6 +460,7 @@ golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d h1:MiWWjyhUzZ+jvhZvloX6ZrUsd
|
|||
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b h1:a0ErnNnPKmhDyIXQvdZr+Lq8dc8xpMeqkF8y5PgQU4Q=
|
||||
golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -496,8 +497,8 @@ golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 h1:VvQyQJN0tSuecqgcIxMWnnf
|
|||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20201208062317-e652b2f42cc7 h1:2OSu5vYyX4LVqZAtqZXnFEcN26SDKIJYlEVIRl1tj8U=
|
||||
golang.org/x/tools v0.0.0-20201208062317-e652b2f42cc7/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2 h1:vEtypaVub6UvKkiXZ2xx9QIvp9TL7sI7xp7vdi2kezA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
|
|
4
http.go
4
http.go
|
@ -109,9 +109,9 @@ func buildHandler() (http.Handler, error) {
|
|||
// IndieAuth
|
||||
r.Route("/indieauth", func(indieauthRouter chi.Router) {
|
||||
indieauthRouter.Use(middleware.NoCache)
|
||||
indieauthRouter.With(authMiddleware, minifier.Middleware).Get("/", indieAuthAuthGet)
|
||||
indieauthRouter.With(minifier.Middleware).Get("/", indieAuthRequest)
|
||||
indieauthRouter.With(authMiddleware).Post("/accept", indieAuthAccept)
|
||||
indieauthRouter.Post("/", indieAuthAuthPost)
|
||||
indieauthRouter.Post("/", indieAuthVerification)
|
||||
indieauthRouter.Get("/token", indieAuthToken)
|
||||
indieauthRouter.Post("/token", indieAuthToken)
|
||||
})
|
||||
|
|
|
@ -3,7 +3,6 @@ package main
|
|||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -18,12 +17,7 @@ func checkIndieAuth(next http.Handler) http.Handler {
|
|||
http.Error(w, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
if !isAllowedHost(httptest.NewRequest(http.MethodGet, tokenData.Me, nil), appConfig.Server.Domain) {
|
||||
http.Error(w, "Forbidden", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
ctx := context.WithValue(r.Context(), "scope", strings.Join(tokenData.Scopes, " "))
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
next.ServeHTTP(w, r.WithContext(context.WithValue(r.Context(), "scope", strings.Join(tokenData.Scopes, " "))))
|
||||
return
|
||||
})
|
||||
}
|
||||
|
|
|
@ -14,85 +14,46 @@ import (
|
|||
)
|
||||
|
||||
// https://www.w3.org/TR/indieauth/
|
||||
// https://indieauth.spec.indieweb.org/
|
||||
|
||||
type indieAuthData struct {
|
||||
Me string
|
||||
ClientID string
|
||||
RedirectURI string
|
||||
State string
|
||||
ResponseType string
|
||||
Scopes []string
|
||||
code string
|
||||
token string
|
||||
time time.Time
|
||||
ClientID string
|
||||
RedirectURI string
|
||||
State string
|
||||
Scopes []string
|
||||
code string
|
||||
token string
|
||||
time time.Time
|
||||
}
|
||||
|
||||
func indieAuthAuthGet(w http.ResponseWriter, r *http.Request) {
|
||||
// Authentication / authorization request
|
||||
func indieAuthRequest(w http.ResponseWriter, r *http.Request) {
|
||||
// Authorization request
|
||||
r.ParseForm()
|
||||
data := &indieAuthData{
|
||||
Me: r.Form.Get("me"),
|
||||
ClientID: r.Form.Get("client_id"),
|
||||
RedirectURI: r.Form.Get("redirect_uri"),
|
||||
State: r.Form.Get("state"),
|
||||
ResponseType: r.Form.Get("response_type"),
|
||||
ClientID: r.Form.Get("client_id"),
|
||||
RedirectURI: r.Form.Get("redirect_uri"),
|
||||
State: r.Form.Get("state"),
|
||||
}
|
||||
if data.ResponseType == "" {
|
||||
data.ResponseType = "id"
|
||||
if rt := r.Form.Get("response_type"); rt != "code" && rt != "id" && rt != "" {
|
||||
http.Error(w, "response_type must be code", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if scope := r.Form.Get("scope"); scope != "" {
|
||||
data.Scopes = strings.Split(scope, " ")
|
||||
}
|
||||
if !isValidProfileURL(data.Me) || !isValidProfileURL(data.ClientID) || !isValidProfileURL(data.RedirectURI) {
|
||||
http.Error(w, "me, client_id and redirect_uri need to by valid URLs", http.StatusBadRequest)
|
||||
if !isValidProfileURL(data.ClientID) || !isValidProfileURL(data.RedirectURI) {
|
||||
http.Error(w, "client_id and redirect_uri need to by valid URLs", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if data.State == "" {
|
||||
http.Error(w, "state must not be empty", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if data.ResponseType != "id" && data.ResponseType != "code" {
|
||||
http.Error(w, "response_type must be empty or id or code", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
// if data.ResponseType == "code" && len(data.Scopes) < 1 {
|
||||
// http.Error(w, "scope is missing or empty", http.StatusBadRequest)
|
||||
// return
|
||||
// }
|
||||
render(w, "indieauth", &renderData{
|
||||
Data: data,
|
||||
})
|
||||
}
|
||||
|
||||
func indieAuthAuthPost(w http.ResponseWriter, r *http.Request) {
|
||||
// Authentication verification
|
||||
r.ParseForm()
|
||||
data := &indieAuthData{
|
||||
code: r.Form.Get("code"),
|
||||
ClientID: r.Form.Get("client_id"),
|
||||
RedirectURI: r.Form.Get("redirect_uri"),
|
||||
}
|
||||
valid, err := data.verifyAuthorization(true)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if !valid {
|
||||
http.Error(w, "Authentication not valid", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
res := &tokenResponse{
|
||||
Me: data.Me,
|
||||
}
|
||||
w.Header().Add(contentType, contentTypeJSONUTF8)
|
||||
err = json.NewEncoder(w).Encode(res)
|
||||
if err != nil {
|
||||
w.Header().Del(contentType)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func isValidProfileURL(profileURL string) bool {
|
||||
u, err := url.Parse(profileURL)
|
||||
if err != nil {
|
||||
|
@ -101,8 +62,6 @@ func isValidProfileURL(profileURL string) bool {
|
|||
if u.Scheme != "http" && u.Scheme != "https" {
|
||||
return false
|
||||
}
|
||||
// Missing: Check path
|
||||
// Missing: Check single/double dot path
|
||||
if u.Fragment != "" {
|
||||
return false
|
||||
}
|
||||
|
@ -120,16 +79,14 @@ func indieAuthAccept(w http.ResponseWriter, r *http.Request) {
|
|||
// Authentication flow
|
||||
r.ParseForm()
|
||||
data := &indieAuthData{
|
||||
Me: r.Form.Get("me"),
|
||||
ClientID: r.Form.Get("client_id"),
|
||||
RedirectURI: r.Form.Get("redirect_uri"),
|
||||
State: r.Form.Get("state"),
|
||||
ResponseType: r.Form.Get("response_type"),
|
||||
Scopes: r.Form["scopes"],
|
||||
time: time.Now(),
|
||||
ClientID: r.Form.Get("client_id"),
|
||||
RedirectURI: r.Form.Get("redirect_uri"),
|
||||
State: r.Form.Get("state"),
|
||||
Scopes: r.Form["scopes"],
|
||||
time: time.Now(),
|
||||
}
|
||||
sha := sha1.New()
|
||||
sha.Write([]byte(data.time.String() + data.Me + data.ClientID))
|
||||
sha.Write([]byte(data.time.String() + data.ClientID))
|
||||
data.code = fmt.Sprintf("%x", sha.Sum(nil))
|
||||
err := data.saveAuthorization()
|
||||
if err != nil {
|
||||
|
@ -147,6 +104,35 @@ type tokenResponse struct {
|
|||
ClientID string `json:"client_id,omitempty"`
|
||||
}
|
||||
|
||||
func indieAuthVerification(w http.ResponseWriter, r *http.Request) {
|
||||
// Authorization verification
|
||||
r.ParseForm()
|
||||
data := &indieAuthData{
|
||||
code: r.Form.Get("code"),
|
||||
ClientID: r.Form.Get("client_id"),
|
||||
RedirectURI: r.Form.Get("redirect_uri"),
|
||||
}
|
||||
valid, err := data.verifyAuthorization()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if !valid {
|
||||
http.Error(w, "Authentication not valid", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
res := &tokenResponse{
|
||||
Me: appConfig.Server.PublicAddress,
|
||||
}
|
||||
w.Header().Add(contentType, contentTypeJSONUTF8)
|
||||
err = json.NewEncoder(w).Encode(res)
|
||||
if err != nil {
|
||||
w.Header().Del(contentType)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func indieAuthToken(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodGet {
|
||||
// Token verification
|
||||
|
@ -157,7 +143,7 @@ func indieAuthToken(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
res := &tokenResponse{
|
||||
Scope: strings.Join(data.Scopes, " "),
|
||||
Me: data.Me,
|
||||
Me: appConfig.Server.PublicAddress,
|
||||
ClientID: data.ClientID,
|
||||
}
|
||||
w.Header().Add(contentType, contentTypeJSONUTF8)
|
||||
|
@ -182,9 +168,8 @@ func indieAuthToken(w http.ResponseWriter, r *http.Request) {
|
|||
code: r.Form.Get("code"),
|
||||
ClientID: r.Form.Get("client_id"),
|
||||
RedirectURI: r.Form.Get("redirect_uri"),
|
||||
Me: r.Form.Get("me"),
|
||||
}
|
||||
valid, err := data.verifyAuthorization(false)
|
||||
valid, err := data.verifyAuthorization()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
|
@ -199,7 +184,7 @@ func indieAuthToken(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
data.time = time.Now()
|
||||
sha := sha1.New()
|
||||
sha.Write([]byte(data.time.String() + data.Me + data.ClientID))
|
||||
sha.Write([]byte(data.time.String() + data.ClientID))
|
||||
data.token = fmt.Sprintf("%x", sha.Sum(nil))
|
||||
err = data.saveToken()
|
||||
if err != nil {
|
||||
|
@ -210,7 +195,7 @@ func indieAuthToken(w http.ResponseWriter, r *http.Request) {
|
|||
TokenType: "Bearer",
|
||||
AccessToken: data.token,
|
||||
Scope: strings.Join(data.Scopes, " "),
|
||||
Me: data.Me,
|
||||
Me: appConfig.Server.PublicAddress,
|
||||
}
|
||||
w.Header().Add(contentType, contentTypeJSONUTF8)
|
||||
err = json.NewEncoder(w).Encode(res)
|
||||
|
@ -227,38 +212,25 @@ func indieAuthToken(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func (data *indieAuthData) saveAuthorization() (err error) {
|
||||
_, err = appDbExec("insert into indieauthauth (time, code, me, client, redirect, scope) values (?, ?, ?, ?, ?, ?)", data.time.Unix(), data.code, data.Me, data.ClientID, data.RedirectURI, strings.Join(data.Scopes, " "))
|
||||
_, err = appDbExec("insert into indieauthauth (time, code, client, redirect, scope) values (?, ?, ?, ?, ?)", data.time.Unix(), data.code, data.ClientID, data.RedirectURI, strings.Join(data.Scopes, " "))
|
||||
return
|
||||
}
|
||||
|
||||
func (data *indieAuthData) verifyAuthorization(authentication bool) (valid bool, err error) {
|
||||
func (data *indieAuthData) verifyAuthorization() (valid bool, err error) {
|
||||
// code valid for 600 seconds
|
||||
if !authentication {
|
||||
row, err := appDbQueryRow("select code, me, client, redirect, scope from indieauthauth where time >= ? and code = ? and me = ? and client = ? and redirect = ?", time.Now().Unix()-600, data.code, data.Me, data.ClientID, data.RedirectURI)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
scope := ""
|
||||
err = row.Scan(&data.code, &data.Me, &data.ClientID, &data.RedirectURI, &scope)
|
||||
if err == sql.ErrNoRows {
|
||||
return false, nil
|
||||
} else if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if scope != "" {
|
||||
data.Scopes = strings.Split(scope, " ")
|
||||
}
|
||||
} else {
|
||||
row, err := appDbQueryRow("select code, me, client, redirect from indieauthauth where time >= ? and code = ? and client = ? and redirect = ?", time.Now().Unix()-600, data.code, data.ClientID, data.RedirectURI)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = row.Scan(&data.code, &data.Me, &data.ClientID, &data.RedirectURI)
|
||||
if err == sql.ErrNoRows {
|
||||
return false, nil
|
||||
} else if err != nil {
|
||||
return false, err
|
||||
}
|
||||
row, err := appDbQueryRow("select code, client, redirect, scope from indieauthauth where time >= ? and code = ? and client = ? and redirect = ?", time.Now().Unix()-600, data.code, data.ClientID, data.RedirectURI)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
scope := ""
|
||||
err = row.Scan(&data.code, &data.ClientID, &data.RedirectURI, &scope)
|
||||
if err == sql.ErrNoRows {
|
||||
return false, nil
|
||||
} else if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if scope != "" {
|
||||
data.Scopes = strings.Split(scope, " ")
|
||||
}
|
||||
valid = true
|
||||
_, err = appDbExec("delete from indieauthauth where code = ? or time < ?", data.code, time.Now().Unix()-600)
|
||||
|
@ -267,7 +239,7 @@ func (data *indieAuthData) verifyAuthorization(authentication bool) (valid bool,
|
|||
}
|
||||
|
||||
func (data *indieAuthData) saveToken() (err error) {
|
||||
_, err = appDbExec("insert into indieauthtoken (time, token, me, client, scope) values (?, ?, ?, ?, ?)", data.time.Unix(), data.token, data.Me, data.ClientID, strings.Join(data.Scopes, " "))
|
||||
_, err = appDbExec("insert into indieauthtoken (time, token, client, scope) values (?, ?, ?, ?)", data.time.Unix(), data.token, data.ClientID, strings.Join(data.Scopes, " "))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -276,13 +248,13 @@ func verifyIndieAuthToken(token string) (data *indieAuthData, err error) {
|
|||
data = &indieAuthData{
|
||||
Scopes: []string{},
|
||||
}
|
||||
row, err := appDbQueryRow("select time, token, me, client, scope from indieauthtoken where token = @token", sql.Named("token", token))
|
||||
row, err := appDbQueryRow("select time, token, client, scope from indieauthtoken where token = @token", sql.Named("token", token))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
timeString := ""
|
||||
scope := ""
|
||||
err = row.Scan(&timeString, &data.token, &data.Me, &data.ClientID, &scope)
|
||||
err = row.Scan(&timeString, &data.token, &data.ClientID, &scope)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, errors.New("token not found")
|
||||
} else if err != nil {
|
||||
|
|
|
@ -15,14 +15,11 @@
|
|||
{{ end }}
|
||||
</ul>
|
||||
{{ end }}
|
||||
<p><strong>me:</strong> {{ .Data.Me }}</p>
|
||||
<p><strong>client_id:</strong> {{ .Data.ClientID }}</p>
|
||||
<p><strong>redirect_uri:</strong> {{ .Data.RedirectURI }}</p>
|
||||
<input type="hidden" name="redirect_uri" value="{{ .Data.RedirectURI }}">
|
||||
<input type="hidden" name="state" value="{{ .Data.State }}">
|
||||
<input type="hidden" id="client_id" name="client_id" value="{{ .Data.ClientID }}">
|
||||
<input type="hidden" name="me" value="{{ .Data.Me }}">
|
||||
<input type="hidden" name="response_type" value="{{ .Data.ResponseType }}">
|
||||
<input type="submit" value="{{ string .Blog.Lang "authenticate" }}">
|
||||
</form>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue