Added authn module for expicitly choosen auth providers

This commit is contained in:
Maxim Lebedev 2021-10-05 11:56:04 +05:00
parent 83b9f56a4f
commit 4f8ac62b7b
Signed by: toby3d
GPG Key ID: 1F14E25B7C119FC5
3 changed files with 112 additions and 0 deletions

View File

@ -0,0 +1,7 @@
package authn
import "context"
type Repository interface {
Fetch(ctx context.Context, me string) ([]string, error)
}

View File

@ -0,0 +1,55 @@
package http
import (
"bytes"
"context"
"net/url"
"github.com/pkg/errors"
http "github.com/valyala/fasthttp"
"willnorris.com/go/microformats"
"source.toby3d.me/website/oauth/internal/authn"
)
type httpAuthnRepository struct {
client *http.Client
}
func NewHTTPAuthnRepository(client *http.Client) authn.Repository {
return &httpAuthnRepository{
client: client,
}
}
func (repo *httpAuthnRepository) Fetch(ctx context.Context, me string) ([]string, error) {
u, err := url.Parse(me)
if err != nil {
return nil, errors.Wrap(err, "failed to parse me as url")
}
req := http.AcquireRequest()
defer http.ReleaseRequest(req)
req.SetRequestURI(u.String())
req.Header.SetMethod(http.MethodGet)
resp := http.AcquireResponse()
defer http.ReleaseResponse(resp)
if err := repo.client.Do(req, resp); err != nil {
return nil, errors.Wrap(err, "failed to make a request to the entered me")
}
data := microformats.Parse(bytes.NewReader(resp.Body()), u)
authn := make([]string, 0)
for rel, values := range data.Rels {
if rel != "authn" {
continue
}
authn = append(authn, values...)
}
return authn, nil
}

View File

@ -0,0 +1,50 @@
package http_test
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
http "github.com/valyala/fasthttp"
repository "source.toby3d.me/website/oauth/internal/authn/repository/http"
"source.toby3d.me/website/oauth/internal/common"
"source.toby3d.me/website/oauth/internal/util"
)
const testBody string = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Example Profile</title>
<link rel="me authn" href="https://user.example.com/">
</head>
<body>
<div class="h-card">
<img src="/photo.png" class="u-photo">
<a rel="me" href="https://user.example.org/">Unsecure profile</a>
<a rel="me authn" href="https://user.example.net/">Secure profile</a>
</div>
</body>
</html>
`
func TestFetch(t *testing.T) {
t.Parallel()
client, _, cleanup := util.TestServe(t, func(ctx *http.RequestCtx) {
ctx.SetStatusCode(http.StatusOK)
ctx.SetContentType(common.MIMETextHTML)
ctx.SetBodyString(testBody)
})
t.Cleanup(cleanup)
result, err := repository.NewHTTPAuthnRepository(client).Fetch(context.TODO(), "https://example.com/")
assert.NoError(t, err)
assert.Equal(t, []string{
"https://user.example.com/",
"https://user.example.net/",
}, result)
}