~mmach/netext73/webkit2gtk

« back to all changes in this revision

Viewing changes to Tools/TestWebKitAPI/Tests/WebCore/LoggedInStatus.cpp

  • Committer: mmach
  • Date: 2023-06-16 17:21:37 UTC
  • Revision ID: netbit73@gmail.com-20230616172137-2rqx6yr96ga9g3kp
1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2019 Apple Inc. All rights reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions
 
6
 * are met:
 
7
 * 1. Redistributions of source code must retain the above copyright
 
8
 *    notice, this list of conditions and the following disclaimer.
 
9
 * 2. Redistributions in binary form must reproduce the above copyright
 
10
 *    notice, this list of conditions and the following disclaimer in the
 
11
 *    documentation and/or other materials provided with the distribution.
 
12
 *
 
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 
14
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 
15
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
16
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 
17
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
18
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
19
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
21
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
22
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 
23
 * THE POSSIBILITY OF SUCH DAMAGE.
 
24
 */
 
25
 
 
26
#include "config.h"
 
27
 
 
28
#include <WebCore/LoggedInStatus.h>
 
29
#include <WebCore/RegistrableDomain.h>
 
30
#include <wtf/Seconds.h>
 
31
#include <wtf/text/StringBuilder.h>
 
32
 
 
33
using namespace WebCore;
 
34
 
 
35
namespace TestWebKitAPI {
 
36
 
 
37
// Positive test cases.
 
38
 
 
39
TEST(LoggedInStatus, DefaultExpiryWebAuthn)
 
40
{
 
41
    RegistrableDomain loginDomain { URL { { }, "https://login.example.com"_s } };
 
42
 
 
43
    auto loggedInResult = LoggedInStatus::create(loginDomain, "admin"_s, LoggedInStatus::CredentialTokenType::HTTPStateToken, LoggedInStatus::AuthenticationType::WebAuthn);
 
44
    auto& loggedIn = loggedInResult.releaseReturnValue().get();
 
45
    auto now = WallTime::now();
 
46
    ASSERT_EQ(loggedIn.registrableDomain().string(), "example.com"_s);
 
47
    ASSERT_EQ(loggedIn.username(), "admin"_s);
 
48
    ASSERT_EQ(loggedIn.credentialTokenType(), LoggedInStatus::CredentialTokenType::HTTPStateToken);
 
49
    ASSERT_EQ(loggedIn.authenticationType(), LoggedInStatus::AuthenticationType::WebAuthn);
 
50
    ASSERT_TRUE(loggedIn.loggedInTime() < now + 60_s);
 
51
    ASSERT_TRUE(loggedIn.loggedInTime() > now - 60_s);
 
52
    ASSERT_TRUE(loggedIn.expiry() < now + LoggedInStatus::TimeToLiveLong + 60_s);
 
53
    ASSERT_TRUE(loggedIn.expiry() > now + LoggedInStatus::TimeToLiveLong - 60_s);
 
54
    ASSERT_FALSE(loggedIn.hasExpired());
 
55
}
 
56
 
 
57
TEST(LoggedInStatus, DefaultExpiryPasswordManager)
 
58
{
 
59
    RegistrableDomain loginDomain { URL { { }, "https://login.example.com"_s } };
 
60
 
 
61
    auto loggedInResult = LoggedInStatus::create(loginDomain, "admin"_s, LoggedInStatus::CredentialTokenType::HTTPStateToken, LoggedInStatus::AuthenticationType::PasswordManager);
 
62
    auto& loggedIn = loggedInResult.releaseReturnValue().get();
 
63
    auto now = WallTime::now();
 
64
    ASSERT_EQ(loggedIn.authenticationType(), LoggedInStatus::AuthenticationType::PasswordManager);
 
65
    ASSERT_TRUE(loggedIn.expiry() < now + LoggedInStatus::TimeToLiveLong + 60_s);
 
66
    ASSERT_TRUE(loggedIn.expiry() > now + LoggedInStatus::TimeToLiveLong - 60_s);
 
67
    ASSERT_FALSE(loggedIn.hasExpired());
 
68
}
 
69
 
 
70
TEST(LoggedInStatus, DefaultExpiryUnmanaged)
 
71
{
 
72
    RegistrableDomain loginDomain { URL { { }, "https://login.example.com"_s } };
 
73
 
 
74
    auto loggedInResult = LoggedInStatus::create(loginDomain, "admin"_s, LoggedInStatus::CredentialTokenType::HTTPStateToken, LoggedInStatus::AuthenticationType::Unmanaged);
 
75
    auto& loggedIn = loggedInResult.releaseReturnValue().get();
 
76
    auto now = WallTime::now();
 
77
    ASSERT_EQ(loggedIn.authenticationType(), LoggedInStatus::AuthenticationType::Unmanaged);
 
78
    ASSERT_TRUE(loggedIn.expiry() < now + LoggedInStatus::TimeToLiveShort + 60_s);
 
79
    ASSERT_TRUE(loggedIn.expiry() > now + LoggedInStatus::TimeToLiveShort - 60_s);
 
80
    ASSERT_FALSE(loggedIn.hasExpired());
 
81
}
 
82
 
 
83
TEST(LoggedInStatus, CustomExpiryBelowLong)
 
84
{
 
85
    RegistrableDomain loginDomain { URL { { }, "https://login.example.com"_s } };
 
86
 
 
87
    auto customExpiry = LoggedInStatus::TimeToLiveLong - 48_h;
 
88
    auto loggedInResult = LoggedInStatus::create(loginDomain, "admin"_s, LoggedInStatus::CredentialTokenType::HTTPStateToken, LoggedInStatus::AuthenticationType::WebAuthn, customExpiry);
 
89
    auto& loggedIn = loggedInResult.releaseReturnValue().get();
 
90
    auto now = WallTime::now();
 
91
    ASSERT_EQ(loggedIn.authenticationType(), LoggedInStatus::AuthenticationType::WebAuthn);
 
92
    ASSERT_TRUE(loggedIn.expiry() < now + customExpiry + 60_s);
 
93
    ASSERT_TRUE(loggedIn.expiry() > now + customExpiry - 60_s);
 
94
    ASSERT_FALSE(loggedIn.hasExpired());
 
95
}
 
96
 
 
97
TEST(LoggedInStatus, CustomExpiryBelowShort)
 
98
{
 
99
    RegistrableDomain loginDomain { URL { { }, "https://login.example.com"_s } };
 
100
 
 
101
    auto customExpiry = LoggedInStatus::TimeToLiveShort - 48_h;
 
102
    auto loggedInResult = LoggedInStatus::create(loginDomain, "admin"_s, LoggedInStatus::CredentialTokenType::HTTPStateToken, LoggedInStatus::AuthenticationType::PasswordManager, customExpiry);
 
103
    auto& loggedIn = loggedInResult.releaseReturnValue().get();
 
104
    auto now = WallTime::now();
 
105
    ASSERT_EQ(loggedIn.authenticationType(), LoggedInStatus::AuthenticationType::PasswordManager);
 
106
    ASSERT_TRUE(loggedIn.expiry() < now + customExpiry + 60_s);
 
107
    ASSERT_TRUE(loggedIn.expiry() > now + customExpiry - 60_s);
 
108
    ASSERT_FALSE(loggedIn.hasExpired());
 
109
}
 
110
 
 
111
TEST(LoggedInStatus, RenewedExpiry)
 
112
{
 
113
    RegistrableDomain loginDomain { URL { { }, "https://login.example.com"_s } };
 
114
 
 
115
    auto customExpiry = LoggedInStatus::TimeToLiveShort - 48_h;
 
116
    auto loggedInResult = LoggedInStatus::create(loginDomain, "admin"_s, LoggedInStatus::CredentialTokenType::HTTPStateToken, LoggedInStatus::AuthenticationType::WebAuthn, customExpiry);
 
117
    auto& loggedIn = loggedInResult.releaseReturnValue().get();
 
118
    auto now = WallTime::now();
 
119
    ASSERT_EQ(loggedIn.authenticationType(), LoggedInStatus::AuthenticationType::WebAuthn);
 
120
    ASSERT_TRUE(loggedIn.expiry() < now + customExpiry + 60_s);
 
121
    ASSERT_TRUE(loggedIn.expiry() > now + customExpiry - 60_s);
 
122
    ASSERT_FALSE(loggedIn.hasExpired());
 
123
    auto newCustomExpiry = 24_h;
 
124
    loggedIn.setTimeToLive(newCustomExpiry);
 
125
    ASSERT_EQ(loggedIn.authenticationType(), LoggedInStatus::AuthenticationType::WebAuthn);
 
126
    ASSERT_TRUE(loggedIn.expiry() < now + newCustomExpiry + 60_s);
 
127
    ASSERT_TRUE(loggedIn.expiry() > now + newCustomExpiry - 60_s);
 
128
    ASSERT_FALSE(loggedIn.hasExpired());
 
129
}
 
130
 
 
131
// Negative test cases.
 
132
 
 
133
TEST(LoggedInStatus, InvalidUsernames)
 
134
{
 
135
    RegistrableDomain loginDomain { URL { { }, "https://login.example.com"_s } };
 
136
 
 
137
    // Whitespace is not allowed.
 
138
    auto loggedInResult = LoggedInStatus::create(loginDomain, "I use spaces"_s, LoggedInStatus::CredentialTokenType::HTTPStateToken, LoggedInStatus::AuthenticationType::WebAuthn);
 
139
    ASSERT_TRUE(loggedInResult.hasException());
 
140
 
 
141
    // Newlines are not allowed.
 
142
    loggedInResult = LoggedInStatus::create(loginDomain, "Enter\nreturn"_s, LoggedInStatus::CredentialTokenType::HTTPStateToken, LoggedInStatus::AuthenticationType::WebAuthn);
 
143
    ASSERT_TRUE(loggedInResult.hasException());
 
144
 
 
145
    // There is a max length to usernames.
 
146
    StringBuilder builder;
 
147
    for (unsigned i = 0; i <= LoggedInStatus::UsernameMaxLength; ++i)
 
148
        builder.append('a');
 
149
    loggedInResult = LoggedInStatus::create(loginDomain, builder.toString(), LoggedInStatus::CredentialTokenType::HTTPStateToken, LoggedInStatus::AuthenticationType::WebAuthn);
 
150
    ASSERT_TRUE(loggedInResult.hasException());
 
151
}
 
152
 
 
153
TEST(LoggedInStatus, ClampedExpiryLong)
 
154
{
 
155
    RegistrableDomain loginDomain { URL { { }, "https://login.example.com"_s } };
 
156
 
 
157
    // Too long expiries for managed auth types should be clamped to LoggedInStatus::TimeToLiveLong.
 
158
    auto loggedInResult = LoggedInStatus::create(loginDomain, "admin"_s, LoggedInStatus::CredentialTokenType::HTTPStateToken, LoggedInStatus::AuthenticationType::WebAuthn, LoggedInStatus::TimeToLiveLong + 24_h);
 
159
    auto& loggedIn = loggedInResult.releaseReturnValue().get();
 
160
    auto now = WallTime::now();
 
161
    ASSERT_EQ(loggedIn.authenticationType(), LoggedInStatus::AuthenticationType::WebAuthn);
 
162
    ASSERT_TRUE(loggedIn.expiry() < now + LoggedInStatus::TimeToLiveLong + 60_s);
 
163
    ASSERT_TRUE(loggedIn.expiry() > now + LoggedInStatus::TimeToLiveLong - 60_s);
 
164
    ASSERT_FALSE(loggedIn.hasExpired());
 
165
 
 
166
    // Renewed, too long expiries for managed auth types should also be clamped to LoggedInStatus::TimeToLiveLong.
 
167
    auto newCustomExpiry = LoggedInStatus::TimeToLiveLong + 24_h;
 
168
    loggedIn.setTimeToLive(newCustomExpiry);
 
169
    ASSERT_EQ(loggedIn.authenticationType(), LoggedInStatus::AuthenticationType::WebAuthn);
 
170
    ASSERT_TRUE(loggedIn.expiry() < now + LoggedInStatus::TimeToLiveLong + 60_s);
 
171
    ASSERT_TRUE(loggedIn.expiry() > now + LoggedInStatus::TimeToLiveLong - 60_s);
 
172
    ASSERT_FALSE(loggedIn.hasExpired());
 
173
}
 
174
 
 
175
TEST(LoggedInStatus, ClampedExpiryShort)
 
176
{
 
177
    RegistrableDomain loginDomain { URL { { }, "https://login.example.com"_s } };
 
178
 
 
179
    // Too long expiries for unmanaged auth types should be clamped to LoggedInStatus::TimeToLiveShort.
 
180
    auto loggedInResult = LoggedInStatus::create(loginDomain, "admin"_s, LoggedInStatus::CredentialTokenType::HTTPStateToken, LoggedInStatus::AuthenticationType::Unmanaged, LoggedInStatus::TimeToLiveShort + 24_h);
 
181
    auto& loggedIn = loggedInResult.releaseReturnValue().get();
 
182
    auto now = WallTime::now();
 
183
    ASSERT_EQ(loggedIn.authenticationType(), LoggedInStatus::AuthenticationType::Unmanaged);
 
184
    ASSERT_TRUE(loggedIn.expiry() < now + LoggedInStatus::TimeToLiveShort + 60_s);
 
185
    ASSERT_TRUE(loggedIn.expiry() > now + LoggedInStatus::TimeToLiveShort - 60_s);
 
186
    ASSERT_FALSE(loggedIn.hasExpired());
 
187
 
 
188
    // Renewed, too long expiries for unmanaged auth types should also be clamped to LoggedInStatus::TimeToLiveShort.
 
189
    auto newCustomExpiry = LoggedInStatus::TimeToLiveShort + 24_h;
 
190
    loggedIn.setTimeToLive(newCustomExpiry);
 
191
    ASSERT_EQ(loggedIn.authenticationType(), LoggedInStatus::AuthenticationType::Unmanaged);
 
192
    ASSERT_TRUE(loggedIn.expiry() < now + LoggedInStatus::TimeToLiveShort + 60_s);
 
193
    ASSERT_TRUE(loggedIn.expiry() > now + LoggedInStatus::TimeToLiveShort - 60_s);
 
194
    ASSERT_FALSE(loggedIn.hasExpired());
 
195
}
 
196
 
 
197
} // namespace TestWebKitAPI