1+ /*
2+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License").
5+ * You may not use this file except in compliance with the License.
6+ * A copy of the License is located at
7+ *
8+ * http://aws.amazon.com/apache2.0
9+ *
10+ * or in the "license" file accompanying this file. This file is distributed
11+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+ * express or implied. See the License for the specific language governing
13+ * permissions and limitations under the License.
14+ */
15+
16+ package software .amazon .awssdk .services .signin .internal ;
17+
18+ import java .security .interfaces .ECPrivateKey ;
19+ import java .security .interfaces .ECPublicKey ;
20+ import java .util .Collections ;
21+ import java .util .List ;
22+ import java .util .concurrent .CompletableFuture ;
23+ import software .amazon .awssdk .core .SdkPlugin ;
24+ import software .amazon .awssdk .core .SdkServiceClientConfiguration ;
25+ import software .amazon .awssdk .http .auth .spi .scheme .AuthScheme ;
26+ import software .amazon .awssdk .http .auth .spi .scheme .AuthSchemeOption ;
27+ import software .amazon .awssdk .http .auth .spi .signer .AsyncSignRequest ;
28+ import software .amazon .awssdk .http .auth .spi .signer .AsyncSignedRequest ;
29+ import software .amazon .awssdk .http .auth .spi .signer .HttpSigner ;
30+ import software .amazon .awssdk .http .auth .spi .signer .SignRequest ;
31+ import software .amazon .awssdk .http .auth .spi .signer .SignedRequest ;
32+ import software .amazon .awssdk .identity .spi .Identity ;
33+ import software .amazon .awssdk .identity .spi .IdentityProvider ;
34+ import software .amazon .awssdk .identity .spi .IdentityProviders ;
35+ import software .amazon .awssdk .identity .spi .ResolveIdentityRequest ;
36+ import software .amazon .awssdk .services .signin .SigninServiceClientConfiguration ;
37+ import software .amazon .awssdk .services .signin .auth .scheme .SigninAuthSchemeParams ;
38+ import software .amazon .awssdk .services .signin .auth .scheme .SigninAuthSchemeProvider ;
39+ import software .amazon .awssdk .utils .Pair ;
40+ import software .amazon .awssdk .utils .Validate ;
41+
42+ public class DpopAuthScheme implements AuthScheme <DpopAuthScheme .DpopIdentity > {
43+ public static final String SCHEME_NAME = "DPOP" ;
44+
45+ private final DpopIdentityProvider identityProvider ;
46+
47+ private DpopAuthScheme (DpopIdentityProvider identityProvider ) {
48+ this .identityProvider = Validate .paramNotNull (identityProvider , "identityProvider" );
49+ }
50+
51+ public static DpopAuthScheme create (ECPublicKey ecPublicKey ) {
52+ return new DpopAuthScheme (DpopIdentityProvider .create (ecPublicKey ));
53+ }
54+
55+ @ Override
56+ public String schemeId () {
57+ return SCHEME_NAME ;
58+ }
59+
60+ @ Override
61+ public IdentityProvider <DpopIdentity > identityProvider (IdentityProviders providers ) {
62+ // we don't currently support adding an arbitrary identityProvider as a request level override
63+ // return the identity provider configured up front instead
64+ return identityProvider ;
65+ }
66+
67+ @ Override
68+ public HttpSigner <DpopIdentity > signer () {
69+ return new DpopSigner ();
70+ }
71+
72+ public static class DpopIdentity implements Identity {
73+ private final ECPublicKey publicKey ;
74+ private final ECPrivateKey privateKey ;
75+
76+ private DpopIdentity (ECPublicKey publicKey , ECPrivateKey privateKey ) {
77+ this .publicKey = publicKey ;
78+ this .privateKey = privateKey ;
79+ }
80+
81+ public static DpopIdentity create (ECPublicKey publicKey , ECPrivateKey privateKey ) {
82+ return new DpopIdentity (publicKey , privateKey );
83+ }
84+
85+ public static DpopIdentity create (String dpopKeyPem ) {
86+ Pair <ECPrivateKey , ECPublicKey > keys = EcKeyLoader .loadSec1Pem (dpopKeyPem );
87+ return new DpopIdentity (keys .right (), keys .left ());
88+ }
89+
90+ public ECPublicKey getPublicKey () {
91+ return publicKey ;
92+ }
93+
94+ public ECPrivateKey getPrivateKey () {
95+ return privateKey ;
96+ }
97+ }
98+
99+ private static class DpopSigner implements HttpSigner <DpopIdentity > {
100+
101+ @ Override
102+ public SignedRequest sign (SignRequest <? extends DpopIdentity > request ) {
103+ return SignedRequest .builder ()
104+ .request (request .request ())
105+ .payload (request .payload ().orElse (null ))
106+ .build ();
107+ }
108+
109+ @ Override
110+ public CompletableFuture <AsyncSignedRequest > signAsync (AsyncSignRequest <? extends DpopIdentity > request ) {
111+ return CompletableFuture .completedFuture (
112+ AsyncSignedRequest .builder ()
113+ .request (request .request ())
114+ .payload (request .payload ().orElse (null ))
115+ .build ());
116+ }
117+ }
118+
119+ private static class DpopIdentityProvider implements IdentityProvider <DpopIdentity > {
120+ private final DpopIdentity identity ;
121+
122+ private DpopIdentityProvider (DpopIdentity identity ) {
123+ this .identity = Validate .paramNotNull (identity , "identity" );
124+ }
125+
126+ public static DpopIdentityProvider create (ECPublicKey ecPublicKey ) {
127+ return new DpopIdentityProvider (DpopIdentity .create (ecPublicKey ));
128+ }
129+
130+ @ Override
131+ public Class <DpopIdentity > identityType () {
132+ return DpopIdentity .class ;
133+ }
134+
135+ @ Override
136+ public CompletableFuture <? extends DpopIdentity > resolveIdentity (ResolveIdentityRequest request ) {
137+ return CompletableFuture .completedFuture (identity );
138+ }
139+ }
140+
141+ public static class DpopAuthSchemeResolver implements SigninAuthSchemeProvider {
142+
143+ @ Override
144+ public List <AuthSchemeOption > resolveAuthScheme (SigninAuthSchemeParams authSchemeParams ) {
145+ return Collections .singletonList (AuthSchemeOption .builder ().schemeId (SCHEME_NAME ).build ());
146+ }
147+ }
148+
149+ public static class DpopAuthPlugin implements SdkPlugin {
150+ private final ECPublicKey ecPublicKey ;
151+
152+
153+ @ Override
154+ public void configureClient (SdkServiceClientConfiguration .Builder config ) {
155+ SigninServiceClientConfiguration .Builder scb =
156+ Validate .isInstanceOf (SigninServiceClientConfiguration .Builder .class , config , "bad" );
157+ scb .authSchemeProvider (new DpopAuthSchemeResolver ());
158+ scb .putAuthScheme (new DpopAuthScheme ());
159+ }
160+ }
161+ }
0 commit comments