+51
atproto/client/admin_auth_test.go
+51
atproto/client/admin_auth_test.go
···
1
+
package client
2
+
3
+
import (
4
+
"context"
5
+
"fmt"
6
+
"net/http"
7
+
"net/http/httptest"
8
+
"testing"
9
+
10
+
"github.com/bluesky-social/indigo/atproto/syntax"
11
+
12
+
"github.com/stretchr/testify/assert"
13
+
)
14
+
15
+
func adminHandler(w http.ResponseWriter, r *http.Request) {
16
+
username, password, ok := r.BasicAuth()
17
+
if ok && username == "admin" && password == "secret" {
18
+
w.Header().Set("Content-Type", "application/json")
19
+
fmt.Fprintln(w, "{\"status\":\"success\"}")
20
+
return
21
+
}
22
+
w.Header().Set("WWW-Authenticate", `Basic realm="admin", charset="UTF-8"`)
23
+
http.Error(w, "Unauthorized", http.StatusUnauthorized)
24
+
}
25
+
26
+
func TestAdminAuth(t *testing.T) {
27
+
assert := assert.New(t)
28
+
ctx := context.Background()
29
+
var apierr *APIError
30
+
31
+
srv := httptest.NewServer(http.HandlerFunc(adminHandler))
32
+
defer srv.Close()
33
+
34
+
{
35
+
c := NewPublicClient(srv.URL)
36
+
err := c.Get(ctx, syntax.NSID("com.example.get"), nil, nil)
37
+
assert.ErrorAs(err, &apierr)
38
+
}
39
+
40
+
{
41
+
c := NewAdminClient(srv.URL, "wrong")
42
+
err := c.Get(ctx, syntax.NSID("com.example.get"), nil, nil)
43
+
assert.ErrorAs(err, &apierr)
44
+
}
45
+
46
+
{
47
+
c := NewAdminClient(srv.URL, "secret")
48
+
err := c.Get(ctx, syntax.NSID("com.example.get"), nil, nil)
49
+
assert.NoError(err)
50
+
}
51
+
}
+2
-2
atproto/client/examples_test.go
+2
-2
atproto/client/examples_test.go
···
17
17
}
18
18
19
19
endpoint := syntax.NSID("app.bsky.actor.getProfile")
20
-
params := map[string]string{
21
-
"actor": "atproto.com",
20
+
params := map[string][]string{
21
+
"actor": []string{"atproto.com"},
22
22
}
23
23
var profile appbsky.ActorDefs_ProfileViewDetailed
24
24
if err := c.Get(ctx, endpoint, params, &profile); err != nil {
+127
atproto/client/password_auth_test.go
+127
atproto/client/password_auth_test.go
···
1
+
package client
2
+
3
+
import (
4
+
"context"
5
+
"encoding/json"
6
+
"fmt"
7
+
"net/http"
8
+
"net/http/httptest"
9
+
"strings"
10
+
"testing"
11
+
12
+
"github.com/bluesky-social/indigo/atproto/identity"
13
+
"github.com/bluesky-social/indigo/atproto/syntax"
14
+
15
+
"github.com/stretchr/testify/assert"
16
+
"github.com/stretchr/testify/require"
17
+
)
18
+
19
+
func pwHandler(w http.ResponseWriter, r *http.Request) {
20
+
switch r.URL.Path {
21
+
case "/xrpc/com.atproto.server.refreshSession":
22
+
//fmt.Println("refreshSession handler...")
23
+
hdr := r.Header.Get("Authorization")
24
+
if hdr != "Bearer refresh1" {
25
+
fmt.Printf("refreshSession header: %s\n", hdr)
26
+
w.Header().Set("WWW-Authenticate", `Bearer`)
27
+
http.Error(w, "Unauthorized", http.StatusUnauthorized)
28
+
return
29
+
}
30
+
w.Header().Set("Content-Type", "application/json")
31
+
json.NewEncoder(w).Encode(map[string]string{
32
+
"did": "did:web:account.example.com",
33
+
"accessJwt": "access2",
34
+
"refreshJwt": "refresh2",
35
+
})
36
+
return
37
+
case "/xrpc/com.atproto.server.createSession":
38
+
if !strings.HasPrefix(r.Header.Get("Content-Type"), "application/json") {
39
+
fmt.Println("createSession Content-Type")
40
+
http.Error(w, "Bad Request", http.StatusBadRequest)
41
+
return
42
+
}
43
+
var body map[string]string
44
+
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
45
+
fmt.Println("createSession JSON")
46
+
http.Error(w, "Bad Request", http.StatusBadRequest)
47
+
return
48
+
}
49
+
if body["identifier"] != "did:web:account.example.com" || body["password"] != "password1" {
50
+
fmt.Println("createSession wrong password")
51
+
http.Error(w, "Bad Request", http.StatusUnauthorized)
52
+
return
53
+
}
54
+
55
+
w.Header().Set("Content-Type", "application/json")
56
+
json.NewEncoder(w).Encode(map[string]string{
57
+
"did": body["identifier"],
58
+
"accessJwt": "access1",
59
+
"refreshJwt": "refresh1",
60
+
})
61
+
return
62
+
case "/xrpc/com.example.get":
63
+
hdr := r.Header.Get("Authorization")
64
+
if hdr == "Bearer access1" {
65
+
w.Header().Set("Content-Type", "application/json")
66
+
fmt.Fprintln(w, "{\"status\":\"success\"}")
67
+
return
68
+
} else {
69
+
fmt.Printf("get header: %s\n", hdr)
70
+
w.Header().Set("WWW-Authenticate", `Bearer`)
71
+
http.Error(w, "Unauthorized", http.StatusUnauthorized)
72
+
return
73
+
}
74
+
case "/xrpc/com.example.expire":
75
+
hdr := r.Header.Get("Authorization")
76
+
if hdr == "Bearer access1" {
77
+
//fmt.Println("forcing refresh...")
78
+
w.Header().Set("Content-Type", "application/json")
79
+
w.WriteHeader(400)
80
+
fmt.Fprintln(w, "{\"error\":\"ExpiredToken\"}")
81
+
return
82
+
} else if hdr == "Bearer access2" {
83
+
w.Header().Set("Content-Type", "application/json")
84
+
fmt.Fprintln(w, "{\"status\":\"success\"}")
85
+
return
86
+
} else {
87
+
fmt.Printf("expire header: %s\n", hdr)
88
+
w.Header().Set("WWW-Authenticate", `Bearer`)
89
+
http.Error(w, "Unauthorized", http.StatusUnauthorized)
90
+
return
91
+
}
92
+
default:
93
+
http.NotFound(w, r)
94
+
return
95
+
}
96
+
}
97
+
98
+
func TestPasswordAuth(t *testing.T) {
99
+
assert := assert.New(t)
100
+
require := require.New(t)
101
+
ctx := context.Background()
102
+
//var apierr *APIError
103
+
104
+
srv := httptest.NewServer(http.HandlerFunc(pwHandler))
105
+
defer srv.Close()
106
+
107
+
dir := identity.NewMockDirectory()
108
+
dir.Insert(identity.Identity{
109
+
DID: "did:web:account.example.com",
110
+
Handle: "user1.example.com",
111
+
Services: map[string]identity.Service{
112
+
"atproto_pds": {
113
+
Type: "AtprotoPersonalDataServer",
114
+
URL: srv.URL,
115
+
},
116
+
},
117
+
})
118
+
119
+
{
120
+
c, err := LoginWithPassword(ctx, &dir, syntax.Handle("user1.example.com").AtIdentifier(), "password1", "")
121
+
require.NoError(err)
122
+
err = c.Get(ctx, syntax.NSID("com.example.get"), nil, nil)
123
+
assert.NoError(err)
124
+
err = c.Get(ctx, syntax.NSID("com.example.expire"), nil, nil)
125
+
assert.NoError(err)
126
+
}
127
+
}