-
-
Notifications
You must be signed in to change notification settings - Fork 930
/
selfservice_login.go
143 lines (118 loc) · 4.18 KB
/
selfservice_login.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package testhelpers
import (
"bytes"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/ory/x/pointerx"
"github.com/ory/viper"
"github.com/ory/kratos/driver"
"github.com/ory/kratos/driver/configuration"
"github.com/ory/kratos/identity"
"github.com/ory/kratos/internal/httpclient/client/common"
"github.com/ory/kratos/internal/httpclient/models"
"github.com/ory/kratos/selfservice/flow/login"
"github.com/ory/kratos/x"
)
func NewLoginUIFlowEchoServer(t *testing.T, reg driver.Registry) *httptest.Server {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
e, err := reg.LoginFlowPersister().GetLoginFlow(r.Context(), x.ParseUUID(r.URL.Query().Get("flow")))
require.NoError(t, err)
reg.Writer().Write(w, r, e)
}))
viper.Set(configuration.ViperKeySelfServiceLoginUI, ts.URL+"/login-ts")
t.Cleanup(ts.Close)
return ts
}
func NewLoginUIWith401Response(t *testing.T) *httptest.Server {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusUnauthorized)
}))
viper.Set(configuration.ViperKeySelfServiceLoginUI, ts.URL+"/login-ts")
t.Cleanup(ts.Close)
return ts
}
func InitializeLoginFlowViaBrowser(t *testing.T, client *http.Client, ts *httptest.Server, forced bool) *common.GetSelfServiceLoginFlowOK {
publicClient := NewSDKClient(ts)
q := ""
if forced {
q = "?refresh=true"
}
res, err := client.Get(ts.URL + login.RouteInitBrowserFlow + q)
require.NoError(t, err)
require.NoError(t, res.Body.Close())
rs, err := publicClient.Common.GetSelfServiceLoginFlow(
common.NewGetSelfServiceLoginFlowParams().WithHTTPClient(client).
WithID(res.Request.URL.Query().Get("flow")),
)
require.NoError(t, err)
assert.Empty(t, rs.Payload.Active)
return rs
}
func InitializeLoginFlowViaAPI(t *testing.T, client *http.Client, ts *httptest.Server, forced bool) *common.InitializeSelfServiceLoginViaAPIFlowOK {
publicClient := NewSDKClient(ts)
rs, err := publicClient.Common.InitializeSelfServiceLoginViaAPIFlow(common.
NewInitializeSelfServiceLoginViaAPIFlowParams().WithHTTPClient(client).WithRefresh(pointerx.Bool(forced)))
require.NoError(t, err)
assert.Empty(t, rs.Payload.Active)
return rs
}
func GetLoginFlowMethodConfig(t *testing.T, rs *models.LoginFlow, id string) *models.LoginFlowMethodConfig {
require.NotEmpty(t, rs.Methods[id])
require.NotEmpty(t, rs.Methods[id].Config)
require.NotEmpty(t, rs.Methods[id].Config.Action)
return rs.Methods[id].Config
}
func LoginMakeRequest(
t *testing.T,
isAPI bool,
f *models.LoginFlowMethodConfig,
hc *http.Client,
values string,
) (string, *http.Response) {
require.NotEmpty(t, f.Action)
res, err := hc.Do(NewRequest(t, isAPI, "POST", pointerx.StringR(f.Action), bytes.NewBufferString(values)))
require.NoError(t, err)
defer res.Body.Close()
return string(x.MustReadAll(res.Body)), res
}
// SubmitLoginForm initiates a login flow (for Browser and API!), fills out the form and modifies
// the form values with `withValues`, and submits the form. Returns the body and checks for expectedStatusCode and
// expectedURL on completion
func SubmitLoginForm(
t *testing.T,
isAPI bool,
hc *http.Client,
publicTS *httptest.Server,
withValues func(v url.Values),
method identity.CredentialsType,
forced bool,
expectedStatusCode int,
expectedURL string,
) string {
if hc == nil {
hc = new(http.Client)
if !isAPI {
hc = NewClientWithCookies(t)
}
}
hc.Transport = NewTransportWithLogger(hc.Transport, t)
var f *models.LoginFlow
if isAPI {
f = InitializeLoginFlowViaAPI(t, hc, publicTS, forced).Payload
} else {
f = InitializeLoginFlowViaBrowser(t, hc, publicTS, forced).Payload
}
time.Sleep(time.Millisecond) // add a bit of delay to allow `1ns` to time out.
config := GetLoginFlowMethodConfig(t, f, method.String())
payload := SDKFormFieldsToURLValues(config.Fields)
withValues(payload)
b, res := LoginMakeRequest(t, isAPI, config, hc, EncodeFormAsJSON(t, isAPI, payload))
assert.EqualValues(t, expectedStatusCode, res.StatusCode, "%s", b)
assert.Contains(t, res.Request.URL.String(), expectedURL, "%+v\n\t%s", res.Request, b)
return b
}