Add Indieauth

master
Peter Stuifzand 6 years ago
parent f9c3dbe6ae
commit d253dea160

@ -0,0 +1,109 @@
package main
import (
"fmt"
"log"
"net/http"
"net/url"
"p83.nl/go/indieauth"
)
const ClientID = "https://p83.nl/track-me"
type IndieAuthHandler struct {
}
func performIndieauthCallback(state, code string, sess *Session) (bool, *indieauth.AuthResponse, error) {
if state != sess.State {
return false, &indieauth.AuthResponse{}, fmt.Errorf("mismatched state %q != %q", state, sess.State)
}
return indieauth.VerifyAuthCode(ClientID, code, sess.RedirectURI, sess.AuthorizationEndpoint)
}
func (h *IndieAuthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
log.Println(r.URL.Path)
sess, err := NewSession(w, r)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
defer sess.Flush()
if r.Method == http.MethodGet {
if r.URL.Path == "" {
fmt.Fprint(w, `
<!doctype html>
<html>
<form action="/auth/login" method="post">
<div class="field">
<div class="control">
<input type="url" name="url" class="input" placeholder="url" />
</div>
</div>
</form>
</html>
`)
return
} else if r.URL.Path == "callback" {
state := r.URL.Query().Get("state")
code := r.URL.Query().Get("code")
verified, authResponse, err := performIndieauthCallback(state, code, sess)
if err != nil {
fmt.Fprintf(w, "ERROR: %q\n", err)
return
}
if verified {
sess.Me = authResponse.Me
sess.LoggedIn = true
log.Printf("SESSION: %#v\n", sess)
if sess.NextURI != "" {
http.Redirect(w, r, sess.NextURI, 302)
} else {
http.Redirect(w, r, "/", 302)
}
return
}
return
}
} else if r.Method == http.MethodPost {
r.ParseForm()
if r.URL.Path == "login" {
// redirect to endpoint
me := r.Form.Get("url")
meURL, err := url.Parse(me)
if err != nil {
http.Error(w, fmt.Sprintf("Bad Request: %s, %s", err.Error(), me), 400)
return
}
endpoints, err := indieauth.GetEndpoints(meURL)
if err != nil {
http.Error(w, fmt.Sprintf("Bad Request: while getting endpoints for %s: %s", me, err.Error()), 400)
return
}
log.Println(endpoints)
authURL, err := url.Parse(endpoints.AuthorizationEndpoint)
if err != nil {
http.Error(w, fmt.Sprintf("Bad Request: %s %s", err.Error(), me), 400)
return
}
log.Println(authURL)
state := RandStringBytes(16)
redirectURI := fmt.Sprintf("%s/auth/callback", "http://localhost:8096")
sess.AuthorizationEndpoint = endpoints.AuthorizationEndpoint
sess.Me = meURL.String()
sess.State = state
sess.RedirectURI = redirectURI
sess.LoggedIn = false
authenticationURL := indieauth.CreateAuthenticationURL(*authURL, meURL.String(), ClientID, redirectURI, state)
http.Redirect(w, r, authenticationURL, 302)
return
}
}
}

@ -133,6 +133,9 @@ func main() {
}
defer db.Close()
indieAuthHandler := &IndieAuthHandler{}
http.Handle("/auth/", http.StripPrefix("/auth/", indieAuthHandler))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
sess, err := NewSession(w, r)
if err != nil {
@ -213,6 +216,7 @@ func main() {
return
}
})
log.Fatal(http.ListenAndServe(":8096", nil))
}

@ -3,13 +3,20 @@ package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"time"
)
type Session struct {
ID string
ID string
LoggedIn bool
Me string
AuthorizationEndpoint string
RedirectURI string
State string
NextURI string
}
func NewSession(w http.ResponseWriter, r *http.Request) (*Session, error) {
@ -22,6 +29,7 @@ func NewSession(w http.ResponseWriter, r *http.Request) (*Session, error) {
if err != nil {
return nil, err
}
log.Printf("%+v", session)
return session, nil
}

Loading…
Cancel
Save