1**Design:** New Feature, **Status:** [Released](../../../README.md) 2 3# Bearer Token Authorization and Token Providers 4 5**What is Bearer Token authorization?** 6 7Bearer Token authorization is a method used to authenticate service request using 8[Bearer Token](https://oauth.net/2/bearer-tokens/) instead of traditional AWS credentials .This is performed by 9populating authorization header with bearer token. 10 11**What is the user experience?** 12 13First, users will be able to configure a profile in the shared SDK configuration files that allows them to 14perform an initial login via the AWS CLI or AWS IDE plugins. For example, this profile might look like this: 15 16 ``` 17 [profile sono] 18 sso_start_url = https://sono.aws 19 sso_region = us-east-1 20 ``` 21 22With this configuration, a user would be able to login via a supported tool such as the AWS CLI: 23 24 ``` 25 $ aws sso login --profile sono 26 ``` 27 28Upon completing this login, a cached token will be available under 29`~/.aws/sso/cache` which will be used by the SDK to perform bearer token 30authorization. 31 32The service will be modeled at the service level to use the `bearer` 33signature version. This client would know how to load the cached token based on the 34profile configuration and populate the bearer authorization header using it. 35This is similar to how an SDK would resolve AWS credentials and perform SigV4 36signing. 37 38*Example* 39 40For example, given a token value of `"mF_9.B5f-4.1JqM"` the value of the 41`Authorization` header would be: `"Bearer mF_9.B5f-4.1JqM"`. A full HTTP 42request may look like the following: 43 44 ``` 45 GET /resource HTTP/1.1 46 Host: server.example.com 47 Authorization: Bearer mF_9.B5f-4.1JqM 48 ``` 49 50## Proposed APIs 51 52When the SDK 2.x client encounters a service or operation that is modeled or configured to use the 53`bearer` signature version, the client will consult the token provider chain to 54derive a token to be used in generating and attaching the authorization to a request. 55 56### API Design for Token/Token Providers and Token Provider Chains 57 58Even though Tokens/TokenProvider and Token Providers is similar to AWS Credentials, 59AWS Credential Provider and AWSCredentialProvider Chain, we will need to provide new interfaces for the following reasons. 60 1. Credentials get finally resolved to accessKeyId and secretAccessKey. These are related to AWS account login. 61 2. SDK should support clients configured for multiple types of credentials (e.g. token and AWS credentials) 62 63#### Token 64 65SDK will support representations of a token that contains additional metadata including the token string and 66the expiration field. 67```java 68@SdkPublicApi 69public interface SdkToken { 70 String token(); 71 Optional<Instant> expirationTime(); 72} 73 74``` 75 76#### Token Provider 77 78To produce a token object SDKs will implement support for token providers and token provider chains. 79The token provider and provider chain interfaces will mirror the existing AWS credential provider 80interfaces in the SDK, but instead return a Token object. 81 82```java 83@FunctionalInterface 84@SdkPublicApi 85public interface SdkTokenProvider { 86 87 SdkToken resolveToken(); 88} 89``` 90SsoTokenProvider is an implementation of SdkTokenProvider that is capable of loading and storing SSO tokens to 91`~/.aws/sso/cache`. This is also capable of refreshing the cached token via the SSO-OIDC service. 92 93 94```java 95 SsoTokenProvider ssoTokenProvider = SsoTokenProvider.builder() 96 .startUrl("https://d-abc123.awsapps.com/start") 97 .build(); 98``` 99 100The StaticTokenProvider represents the simplest possible token provider. 101It simply returns a static token string and has an optional expiration. 102 103```java 104 StaticTokenProvider provider = StaticTokenProvider.create(bearerToken); 105``` 106 107#### Token Provider Chains 108 109SdkTokenProviderChain is an implementation of SdkTokenProvider that chains together multiple token providers. 110The public method of this class is exactly same as [AwsCredentialsProviderChain](https://github.com/aws/aws-sdk-java-v2/blob/master/core/auth/src/main/java/software/amazon/awssdk/auth/credentials/AwsCredentialsProviderChain.java) 111except it resolves the Token providers. 112 113#### ClientBuilder API to set Token Privder 114 115A new API will be added in [AwsClientBuilder](https://github.com/aws/aws-sdk-java-v2/blob/master/core/aws-core/src/main/java/software/amazon/awssdk/awscore/client/builder/AwsClientBuilder.java) 116to set the tokenProvider to a client. 117 118```java 119 120 SdkTokenProviderChain TOKEN_PROVIDER_CHAIN = DefaultSdkTokenProvderChain.create(); 121 ServiceClient.builder() 122 .region(REGION) 123 .tokenProvider(TOKEN_PROVIDER_CHAIN) 124 .build(); 125``` 126 127 128### Bearer Token Authorizer 129 130Bearer Token Authorization will be done by BearerTokenSigner that will update the Authorization header with bearer 131token that is resolved from Token Provider. 132 133```java 134@SdkPublicApi 135public final class BearerTokenSigner implements Signer { 136 137 @Override 138 public CredentialType credentialType() { 139 return CredentialType.TOKEN; 140 } 141 142 @Override 143 public SdkHttpFullRequest sign(SdkHttpFullRequest request, ExecutionAttributes executionAttributes) { 144 /** 145 * doSign will do following 146 * 1. Resolve token from Token Provider 147 * 2. Set the Authorization header by filling in the token to the following format string: "Bearer {token}". 148 */ 149 return doSign(request, executionAttributes); 150 } 151 public static BearerTokenSigner create() { 152 return new BearerTokenSigner(); 153 } 154} 155 156``` 157#### ClientBuilder API to set Bearer Token Signer 158 159A new AdvancedOption setting `BEARER_SIGNER` will be created to add bearer signer 160 161```java 162 163 ServiceClient.builder() 164 .region(REGION) 165 .overrideConfiguration( 166 ClientOverrideConfiguration.builder() 167 .putAdvancedOption(BEARER_SIGNER, DefaultBearerTokenSigner.create()) 168 .build()) 169 .build(); 170``` 171 172Also, ClientBuilder can be updated with Bearer Token Signer by using existing `SIGNER` advancedOption 173```java 174 serviceClient.builder() 175 .region(REGION) 176 .overrideConfiguration( 177 ClientOverrideConfiguration.builder() 178 .putAdvancedOption(SIGNER, DefaultBearerTokenSigner.create()) 179 .build()) 180``` 181#### OperationRequest Builder API to set Bearer Token Signer 182Bearer Token Signer can be set at request level by overriding configuration for request operation. 183A new API `bearerTokenSigner(BearerTokenSigner bearerTokenSigner)` will be added in 184[RequestOverrideConfiguration](https://github.com/aws/aws-sdk-java-v2/blob/master/core/aws-core/src/main/java/software/amazon/awssdk/awscore/AwsRequestOverrideConfiguration.java). 185 186```java 187 serviceClient.operation(OperationRequest.builder() 188 .overrideConfiguration(o -> o.bearerTokenSigner(DefaultBearerTokenSigner.create())) 189 .build()); 190``` 191 192Also, BearerTokenSigner can be updated by setting signer on RequestOverrideConfiguration. 193 194```java 195 serviceClient.operation(OperationRequest.builder() 196 .overrideConfiguration(o -> o.signer(DefaultBearerTokenSigner.create())) 197 .build()); 198``` 199