1/*
2 * Copyright (C) 2017 Google Inc. All rights reserved.
3 * Copyright (C) 2017 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "CredentialsContainer.h"
29
30#if ENABLE(WEB_AUTHN)
31
32#include "AbortSignal.h"
33#include "CredentialCreationOptions.h"
34#include "CredentialRequestOptions.h"
35#include "Document.h"
36#include "ExceptionOr.h"
37#include "JSDOMPromiseDeferred.h"
38#include "Page.h"
39#include "SecurityOrigin.h"
40
41namespace WebCore {
42
43CredentialsContainer::CredentialsContainer(WeakPtr<Document>&& document)
44 : m_document(WTFMove(document))
45{
46}
47
48bool CredentialsContainer::doesHaveSameOriginAsItsAncestors()
49{
50 // The following implements https://w3c.github.io/webappsec-credential-management/#same-origin-with-its-ancestors
51 // as of 14 November 2017.
52 if (!m_document)
53 return false;
54
55 auto& origin = m_document->securityOrigin();
56 for (auto* document = m_document->parentDocument(); document; document = document->parentDocument()) {
57 if (!origin.isSameOriginAs(document->securityOrigin()))
58 return false;
59 }
60 return true;
61}
62
63void CredentialsContainer::get(CredentialRequestOptions&& options, CredentialPromise&& promise)
64{
65 // The following implements https://www.w3.org/TR/credential-management-1/#algorithm-request as of 4 August 2017
66 // with enhancement from 14 November 2017 Editor's Draft.
67 if (!m_document || !m_document->page()) {
68 promise.reject(Exception { NotSupportedError });
69 return;
70 }
71 if (options.signal && options.signal->aborted()) {
72 promise.reject(Exception { AbortError, "Aborted by AbortSignal."_s });
73 return;
74 }
75 // Step 1-2.
76 ASSERT(m_document->isSecureContext());
77
78 // Step 3 is enhanced with doesHaveSameOriginAsItsAncestors.
79 // Step 4-6. Shortcut as we only support PublicKeyCredential which can only
80 // be requested from [[discoverFromExternalSource]].
81 if (!options.publicKey) {
82 promise.reject(Exception { NotSupportedError, "Only PublicKeyCredential is supported."_s });
83 return;
84 }
85
86 // Extra.
87 if (!m_document->hasFocus()) {
88 promise.reject(Exception { NotAllowedError, "The document is not focused."_s });
89 return;
90 }
91
92 m_document->page()->authenticatorCoordinator().discoverFromExternalSource(m_document->securityOrigin(), options.publicKey.value(), doesHaveSameOriginAsItsAncestors(), WTFMove(options.signal), WTFMove(promise));
93}
94
95void CredentialsContainer::store(const BasicCredential&, CredentialPromise&& promise)
96{
97 promise.reject(Exception { NotSupportedError, "Not implemented."_s });
98}
99
100void CredentialsContainer::isCreate(CredentialCreationOptions&& options, CredentialPromise&& promise)
101{
102 // The following implements https://www.w3.org/TR/credential-management-1/#algorithm-create as of 4 August 2017
103 // with enhancement from 14 November 2017 Editor's Draft.
104 if (!m_document || !m_document->page()) {
105 promise.reject(Exception { NotSupportedError });
106 return;
107 }
108 if (options.signal && options.signal->aborted()) {
109 promise.reject(Exception { AbortError, "Aborted by AbortSignal."_s });
110 return;
111 }
112 // Step 1-2.
113 ASSERT(m_document->isSecureContext());
114
115 // Step 3-7. Shortcut as we only support one kind of credentials.
116 if (!options.publicKey) {
117 promise.reject(Exception { NotSupportedError, "Only PublicKeyCredential is supported."_s });
118 return;
119 }
120
121 // Extra.
122 if (!m_document->hasFocus()) {
123 promise.reject(Exception { NotAllowedError, "The document is not focused."_s });
124 return;
125 }
126
127 m_document->page()->authenticatorCoordinator().create(m_document->securityOrigin(), options.publicKey.value(), doesHaveSameOriginAsItsAncestors(), WTFMove(options.signal), WTFMove(promise));
128}
129
130void CredentialsContainer::preventSilentAccess(DOMPromiseDeferred<void>&& promise) const
131{
132 promise.reject(Exception { NotSupportedError, "Not implemented."_s });
133}
134
135} // namespace WebCore
136
137#endif // ENABLE(WEB_AUTHN)
138