Skip to content

Commit

Permalink
Fix CognitoIdentityCredentials (#2944)
Browse files Browse the repository at this point in the history
  • Loading branch information
jterapin authored Nov 14, 2023
1 parent acbe006 commit bd72278
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 26 deletions.
2 changes: 2 additions & 0 deletions gems/aws-sdk-cognitoidentity/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Unreleased Changes
------------------

* Issue - Pass provided `logins` when a `CognitoIdentityCredentials` client is created (#2941).

1.49.0 (2023-09-27)
------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ module CognitoIdentity
#
# ## Refreshing Credentials from Identity Service
#
# The CognitoIdentityCredentials will auto-refresh the AWS credentials from
# The `CognitoIdentityCredentials` will auto-refresh the AWS credentials from
# Cognito. In addition to AWS credentials expiring after a given amount of
# time, the login token from the identity provider will also expire.
# Once this token expires, it will not be usable to refresh AWS credentials,
Expand All @@ -32,19 +32,18 @@ module CognitoIdentity
# supported by most identity providers. Consult the documentation for
# the identity provider for refreshing tokens. Once the refreshed token is
# acquired, you should make sure to update this new token in the
# CognitoIdentityCredentials object's {logins} property. The following
# `CognitoIdentityCredentials` object's {logins} property. The following
# code will update the WebIdentityToken, assuming you have retrieved
# an updated token from the identity provider:
#
# AWS.config.credentials.logins['graph.facebook.com'] = updatedToken;
# AWS.config.credentials.refresh! # required only if authentication state has changed
# cognito_credentials.logins['graph.facebook.com'] = updatedToken;
# cognito_credentials.refresh! # required only if authentication state has changed
#
# The CognitoIdentityCredentials also provides a `before_refresh` callback
# The `CognitoIdentityCredentials` also provides a `before_refresh` callback
# that can be used to help manage refreshing identity provider tokens.
# `before_refresh` is called when AWS credentials are required and need
# to be refreshed and it has access to the CognitoIdentityCredentials object.
class CognitoIdentityCredentials

include CredentialProvider
include RefreshingCredentials

Expand All @@ -54,8 +53,8 @@ class CognitoIdentityCredentials
# identifier in the format REGION:GUID
#
# @option options [String] :identity_pool_id Required unless identity_id
# is provided. A Amazon Cognito
# Identity Pool ID)in the format REGION:GUID.
# is provided. An Amazon Cognito Identity Pool ID in the
# format REGION:GUID.
#
# @option options [Hash<String,String>] :logins A set of optional
# name-value pairs that map provider names to provider tokens.
Expand All @@ -69,16 +68,15 @@ class CognitoIdentityCredentials
# that do not support role customization.
#
# @option options [Callable] before_refresh Proc called before
# credentials are refreshed from Cognito. Useful for updating logins/
# auth tokens. `before_refresh` is called when AWS credentials are
# required and need to be refreshed. Login tokens can be refreshed using
# the following example:
# credentials are refreshed from Cognito. `before_refresh` is called
# when AWS credentials are required and need to be refreshed.
# Login tokens can be refreshed using the following example:
#
# before_refresh = Proc.new do |cognito_credentials| do
# cognito_credentials.logins['graph.facebook.com'] = update_token
# end
#
# @option options [STS::CognitoIdentity] :client Optional CognitoIdentity
# @option options [CognitoIdentity::Client] :client Optional CognitoIdentity
# client. If not provided, a client will be constructed.
def initialize(options = {})
@identity_pool_id = options.delete(:identity_pool_id)
Expand All @@ -88,9 +86,9 @@ def initialize(options = {})
@async_refresh = false

client_opts = {}
options.each_pair { |k,v| client_opts[k] = v unless CLIENT_EXCLUDE_OPTIONS.include?(k) }
options.each_pair { |k, v| client_opts[k] = v unless CLIENT_EXCLUDE_OPTIONS.include?(k) }

if !@identity_pool_id && !@identity_id
unless @identity_pool_id || @identity_id
raise ArgumentError,
'Must provide either identity_pool_id or identity_id'
end
Expand All @@ -109,19 +107,21 @@ def initialize(options = {})

# @return [String]
def identity_id
@identity_id ||= @client
.get_id(identity_pool_id: @identity_pool_id)
.identity_id
@identity_id ||= @client.get_id(
identity_pool_id: @identity_pool_id,
logins: @logins
).identity_id
end

private

def refresh
@before_refresh.call(self) if @before_refresh
@before_refresh&.call(self)

resp = @client.get_credentials_for_identity(
identity_id: identity_id,
custom_role_arn: @custom_role_arn
custom_role_arn: @custom_role_arn,
logins: @logins
)

@credentials = Credentials.new(
Expand All @@ -134,4 +134,3 @@ def refresh
end
end
end

Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ module CognitoIdentity

let(:identity_id) { 'identity_id' }
let(:identity_pool_id) { 'pool_id' }

let(:logins) do
{ 'login_provider' => 'login_token' }
end
let(:resp) { double('client-resp', credentials: cognito_creds) }

describe '#initialize' do
Expand Down Expand Up @@ -88,11 +90,13 @@ module CognitoIdentity

it 'gets identity_id from the identity_pool_id' do
expect(client).to receive(:get_id)
.with(identity_pool_id: identity_pool_id)
.with(identity_pool_id: identity_pool_id, logins: logins)
.and_return(double("getid", identity_id: identity_id))

creds = CognitoIdentityCredentials.new(
client: client, identity_pool_id: identity_pool_id
client: client,
identity_pool_id: identity_pool_id,
logins: logins
)

expect(creds.identity_id).to eq(identity_id)
Expand All @@ -102,7 +106,7 @@ module CognitoIdentity
describe '#refresh' do
it 'extracts credentials and expiration from the response' do
expect(client).to receive(:get_credentials_for_identity)
.with(identity_id: identity_id, custom_role_arn: nil)
.with(identity_id: identity_id, custom_role_arn: nil, logins: {})
.and_return(resp)

creds = CognitoIdentityCredentials.new(
Expand Down Expand Up @@ -134,8 +138,21 @@ module CognitoIdentity

expect(before_refresh_called).to be(true)
end
end

it 'passes logins to the credentials' do
expect(client).to receive(:get_credentials_for_identity)
.with(identity_id: identity_id, logins: logins, custom_role_arn: nil)
.and_return(resp)

creds = CognitoIdentityCredentials.new(
client: client,
identity_id: identity_id,
logins: logins
)

expect(creds.logins).to eq(logins)
end
end
end
end
end

0 comments on commit bd72278

Please sign in to comment.