Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible to set current credentials manually? #825

Closed
Guitarkalle opened this issue May 11, 2018 · 59 comments
Closed

Possible to set current credentials manually? #825

Guitarkalle opened this issue May 11, 2018 · 59 comments
Assignees
Labels
Auth Related to Auth components/category feature-request Request a new feature

Comments

@Guitarkalle
Copy link

Is it possible to set the credentials for the current user manually in an easy way?

I have a custom login using the authorize and token endpoints (custom login interface), and wish to load the credentials in the Auth library to continue using it in the rest of my app.

The Auth lib has support for parsing a request from the hosted UI containing code and state parameters. It then makes a post to the TOKEN endpoint and loads the credentials. It doesn't seem to have support for PKCE sadly and it doesn't check the STATE parameter either I think to make sure it's correct? see getCodeQueryParameter in CognitoAuth.js for the parsing.

So I am wondering if it's possible to supply the JWT token to Auth for it to load the user etc.
I basically want to call CognitoAuth.onSuccessExchangeForToken

Is there an easy way to get access to the CognitoAuth instance in the Auth component (import { Auth } from 'aws-amplify';) so I can call its methods? One idea could be to expose a method for calling the /authorize endpoint yourself so you can initiate an authorization flow. As well as adding PKCE support for the flow. The rest of the functionality seems to be there already

@UnleashedMind UnleashedMind added the investigating This issue is being investigated label May 11, 2018
@powerful23 powerful23 added feature-request Request a new feature Auth Related to Auth components/category and removed investigating This issue is being investigated labels May 11, 2018
@justinwaite
Copy link

This exactly. I am using React Native which current has no support for using the Hosted UI through AppSync. I am using Expo and it's provided AuthSession class to initiate login with FaceBook using my cognito user pool domain:

  const clientId = "<my client id>";
  let redirectUrl = AuthSession.getRedirectUrl()
  let result = await AuthSession.startAsync({
    authUrl: "".concat(
      `https://<mydomain>.auth.us-west-2.amazoncognito.com/authorize?response_type=code`,
      `&client_id=${clientId}`,
      `&identity_provider=Facebook`,
      `&redirect_uri=${encodeURIComponent(redirectUrl)}`,
      `&scope=profile+email+openid`
    )
  })

This works exactly as I expect it to: my user is created and I am given the access token for my cognito user. Now I would love to be able to supply this token to Amplify's Auth class to let it know that I have indeed authenticated my user.

Without hacking up the library on my own, is it possible to do this? This is a blocker for our app to be able to continue (we do NOT want to federate Facebook login through a Cognito Identity Pool, but rather through the User Pool).

@Guitarkalle
Copy link
Author

Guitarkalle commented May 20, 2018

@jdeanwaite
Ah, when using native I guess not even the url parsing function works? I am developing a web page and in that case it loads the jwt token correctly (i am using a full http get when claling the authorize end point). It's just that it doesn't work with PKCE and loading the credentials manually seems a hassle since the methods are not exposed.

Bit off topic: Does the authorize endpoint / custom UI support the native facebook app for login? Or will you get redirected to the web version of facebook and have to supply credentials?

@epicfaace
Copy link
Contributor

+1

@lcrodriguez
Copy link

Anyone got a solution to this? I was trying the same thing.

@justinwaite
Copy link

justinwaite commented Aug 5, 2018 via email

@lcrodriguez
Copy link

lcrodriguez commented Aug 5, 2018 via email

@justinwaite
Copy link

justinwaite commented Aug 5, 2018 via email

@epicfaace
Copy link
Contributor

@lcrodriguez I did end up finding a solution for this, at least for my particular use case. What you do is, set the jwt to something else in local storage. Then, when adding the Authorization header to an API call, you can pass in the jwt stored in localStorage

Additionally, in all the functions in which you get a user's profile info, etc., you would need to check and see if your custom jwt is stored in localStorage; if it is, decode it yourself and then set the appropriate attributes you want.

Code I used for API endpoint:


const asyncLocalStorage = {
    setItem: function (key, value) {
        return Promise.resolve().then(function () {
            localStorage.setItem(key, value);
        });
    },
    getItem: function (key) {
        return Promise.resolve().then(function () {
            return localStorage.getItem(key);
        });
    }
};


Amplify.configure({
  Auth: {
  // REQUIRED - Amazon Cognito Identity Pool ID
      identityPoolId: ...,
  // REQUIRED - Amazon Cognito Region
      region: 'us-east-1',
  // OPTIONAL - Amazon Cognito User Pool ID
      userPoolId: USER_POOL_ID,
  // OPTIONAL - Amazon Cognito Web Client ID (26-char alphanumeric string)
      userPoolWebClientId: COGNITO_CLIENT_ID,
  // OPTIONAL - Enforce user authentication prior to accessing AWS resources or not
      mandatorySignIn: false
  },
  API: {
    endpoints: [
        {
            name: "name",
            endpoint: ENDPOINT_URL,
            custom_header: async () => { 
                try {
                    return { Authorization: (await Auth.currentSession()).idToken.jwtToken }
                }
                catch (e) {
                    console.error(e);
                    return { Authorization: await asyncLocalStorage.getItem("jwt") } 
                }
            }
        }
    ]
  }
});

Code I used for getting a user's attributes; it's essentially overriding Auth.currentAuthenticatedUser:

function getCurrentUser() {
  let jwt = localStorage.getItem("jwt");
  if (jwt) {
    return API.post("api", "authorize", { "body": { "token": jwt } })
      .then(e => {
        let attributes: IUserAttributes = { "name": e.name, "email": e.email, "email_verified": e.email_verified };
        return {
          "username": e["cognito:username"],
          attributes
        }
      })
      .catch(e => Auth.currentAuthenticatedUser())
  }
  else {
    return Auth.currentAuthenticatedUser();
  }
}

@lcrodriguez
Copy link

Thanks much! I will give it a try in a few days and get back to you.

@powerful23
Copy link
Contributor

powerful23 commented Aug 15, 2018

@Guitarkalle about this feature request if I am understanding correctly, you want to pass the tokens(idToken, accessToken) to the Auth module manually, for example:

let { idToken, accessToken, refreshToken, user } = somewhere();

Auth.setCognitoSession({
    idToken,
    accessToken,
    refreshToken,
    user
}).then(user => {
    console.log(user); // The Cognito user object
});

// After doing that, you will create a cognito session for you. Amplify library will store this session into 
// cache and return a Cognito user for you. An Aws credentials will also be loaded into library if you have 
// configured your Cognito Federated Idnetity Pool

@epicfaace
Copy link
Contributor

@powerful23 exactly.

@engharb
Copy link

engharb commented Sep 26, 2018

@powerful23 exactly as you mentioned

Auth.setCognitoSession

but the problem is that we receive only id_Token, access_token and expires_in in the response URL?!!

@powerful23
Copy link
Contributor

@engharb well that user could be optional. If not set, we can try to extract the user name from the jwt token.

@engharb
Copy link

engharb commented Sep 27, 2018

@powerful23 I mean that:
1- Auth.setCognitoSession is not yet implemented,
2- by calling the following link we receive only accessToken and idToken no refreshToken is available
https://<your_user_pool_domain>/login?response_type=code&client_id=<your_client_id>&redirect_uri=https://www.example.com

@powerful23
Copy link
Contributor

@engharb yes it's still in implementation. The refreshToken will be optional in that session object. We are trying to make it as generic as possible to handle different cases.

@jannikweichert
Copy link

@powerful23 Any updates on this?

@powerful23
Copy link
Contributor

@jannikweichert still working on it.

@engharb
Copy link

engharb commented Oct 4, 2018

I have followed #1143 and using amazon-cognito-auth-js to SignUp/SignIn using Social Accounts i.e FB, Google providers.

@ChrisWun
Copy link

@powerful23 I definitely need this.

@Guitarkalle about this feature request if I am understanding correctly, you want to pass the tokens(idToken, accessToken) to the Auth module manually, for example:

let { idToken, accessToken, refreshToken, user } = somewhere();

Auth.setCognitoSession({
    idToken,
    accessToken,
    refreshToken,
    user
}).then(user => {
    console.log(user); // The Cognito user object
});

// After doing that, you will create a cognito session for you. Amplify library will store this session into 
// cache and return a Cognito user for you. An Aws credentials will also be loaded into library if you have 
// configured your Cognito Federated Idnetity Pool

@indrsidhu
Copy link

indrsidhu commented Nov 4, 2018

I am looking for something same.
Using Web AWS UI after successful login i get response /?code=
Then i POST it to /oauth2/token for exchange it for Token
in response i have

const tokenPayload = {
	access_token  : response.data.access_token,
	id_token      : response.data.id_token,
	refresh_token : response.data.refresh_token
}

I want to create user Pool to make local login,like we have in aws-amplify
but i am unable to find solution to set this session manually, help me if someone had worked around this problem

@engharb
Copy link

engharb commented Nov 5, 2018

@indrsidhu,
Here is my impl. I used:

// user.js
import {CognitoAuth} from './dist/amazon-cognito-auth';

export function isAuthenticated() {

    return new Promise(function(resolve, reject) {
        Amplify.Auth.currentAuthenticatedUser().then(
            function (value) {
                resolve(value);
            }
        ).catch(
            function (reason) {
                reject(reason);
            }
        );
    });
}
export function onLoad() {
    // initialize Cognito-Auth instance
    var auth = initCognitoSDK();

    // read the returned social login url
    var curUrl = window.location.href;
    // store the params locally
    auth.parseCognitoWebResponse(curUrl);

    //alert(auth.isUserSignedIn());

    // create/update User Cognito instance
    
    this.getCurrentSession();

    //return auth;
}
export function getCurrentSession() {
    return new Promise(function(resolve, reject) {
        Amplify.Auth.currentSession().then(
            function (value) {
                resolve(value)
            }).catch(function (reason) {
            reject(reason)
        });
    });
}

/**
 * initialize a Cognito-Auth instance
 * @returns {*}
 */
export function initCognitoSDK() {
   
    // loads the configuration from aws_exports
    var authData = {
        ClientId : aws_exports.aws_user_pools_web_client_id, // Your client id here
        AppWebDomain : aws_exports.aws_cognito_user_pool_domain,
        TokenScopesArray : ['phone', 'email', 'profile','openid', 'aws.cognito.signin.user.admin'], // e.g.['phone', 'email', 'profile','openid', 'aws.cognito.signin.user.admin'],
        RedirectUriSignIn : 'https://abc',
        RedirectUriSignOut : 'https://abc',
        IdentityProvider : 'Facebook', // e.g. 'Facebook',
        UserPoolId : aws_exports.aws_user_pools_id, // Your user pool id here
    };

    var auth = new CognitoAuth(authData);

    auth.userhandler = {
        onSuccess: function (result) {
            //auth.getSession();
            console.info("Your login Status: " + auth.getState());
        },
        onFailure: function (err) {
            console.log("Error while logging: " + JSON.stringify(err));
        }
    };

    
    return auth;
}

// my login template I used to call the onLoad function after
// you succeeded to login using i.e FB account and then AWS redirects you
// to your callback url.
// Then isAuthenticated reads the session tokens and then do what ever you want
$(document).ready(function () {
    // in order to login using Social account
    User.onLoad();

    User.isAuthenticated().then(
        function (value) {
            console.log(JSON.stringify(value));
    
            $("#LoginForm").submit();
        }
    ).catch(
        function (err) {
            console.log("User not yet logged in!");
        }
    );
});

@engharb
Copy link

engharb commented Nov 5, 2018

@powerful23 Do you have already the new Implementation or features for Social Login in User-Pool (Amplify-js)?

Currently I am able to login to user-pool using i.e FB/Google account (in my Website) and using 'amazon-cognito-auth'. Then I can see the new record in User-Pool logged in users.

(in my Mobile app) Is there any possibility to enable the user to login using new username created in user-pool with 'kind of' random generated password.?

Of course the login doe not work for Mobile Application using the Amplify.

@tmjordan
Copy link

@engharb Yes i see. I found a way to implement that and now it's working.

@tmjordan
Copy link

If it can help someone, here is the example of code that i used.
It uses Expo to open the web browser.
If you don't use expo, you can adapt the code to open the browser in a different way
You must also have to install or import the Buffer library ( npm install --save Buffer).
And finally you must adapt the authData const, to fit your environment.

@tmjordan
Copy link

`import React from 'react';
import { View, Text, Linking, StyleSheet, TouchableOpacity } from 'react-native';
import { Auth } from 'aws-amplify';
import { StorageHelper } from '@aws-amplify/core';
import { WebBrowser } from 'expo';
import { Buffer } from 'buffer';

const storage = new StorageHelper().getStorage();

const authData = {
ClientId: 'your_app_client id'',
AppWebDomain: 'https://something.auth.us-east-2.amazoncognito.com',
RedirectUriSignIn: 'myapp://',
IdentityProvider: 'Facebook',
};

Auth.configure({
storage: storage
});

export const decodePayload = (jwtToken) => {
const payload = jwtToken.split('.')[1];
try {
return JSON.parse(Buffer.from(payload, 'base64').toString('utf8'));
} catch (err) {
return {};
}
};

export const calculateClockDrift = (iatAccessToken, iatIdToken) => {
const now = Math.floor(new Date() / 1000);
const iat = Math.min(iatAccessToken, iatIdToken);
return now - iat;
};

export class Login extends React.Component {

componentDidMount() {
    Linking.addEventListener('url', (event) => {
        Expo.WebBrowser.dismissBrowser();
        this._handleOpenURL(event.url);
    });
}

_handlePressButtonAsync = async () => {
    const url = authData.AppWebDomain+'/oauth2/authorize?response_type=code&client_id='+authData.ClientId+'&redirect_uri='+authData.RedirectUriSignIn+'&identity_provider='+authData.IdentityProvider;
    await WebBrowser.openBrowserAsync(url);
};

_handleOpenURL = url => {
    try {
        const code = url.match(/code=([^&]+)/)[1];
        this.getTokenByCode(code);
    }
    catch (error) {
        console.log(error)
    }
};

getTokenByCode = (code) => {
    const details = {
        grant_type: "authorization_code",
        code,
        client_id: authData.ClientId,
        redirect_uri: authData.RedirectUriSignIn
    };
    const formBody = Object.keys(details)
        .map(
            key => `${encodeURIComponent(key)}=${encodeURIComponent(details[key])}`
        )
        .join("&");

    fetch(
        authData.AppWebDomain+"/oauth2/token",
        {
            method: "POST",
            headers: {
                "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
            },
            body: formBody
        }
    )
    .then(res => {
        res.json().then(function(data) {

            const idTokenData = decodePayload(data['id_token']);
            const accessTokenData = decodePayload(data['access_token']);

            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.LastAuthUser', idTokenData['cognito:username']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.idToken', data['id_token']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.accessToken', data['access_token']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.refreshToken', data['refresh_token']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.clockDrift', ''+calculateClockDrift(accessTokenData['iat'], idTokenData['iat'])+'');

            Auth.currentUserInfo()
                .then((res) => {
                    console.log(res);
                    alert('User signed in'+'\n'+'Check the logs');
                })
                .catch((res) => {
                    console.log(res);
                });
        });
    })
    .catch(error => {
        console.error(error);
    });
};

render = () => (
    <View style={styles.main_container}>
        <TouchableOpacity onPress={this._handlePressButtonAsync}>
            <Text>Login with facebook</Text>
        </TouchableOpacity>
    </View>
);

}

const styles = StyleSheet.create({
main_container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
});
`

@tmjordan
Copy link

Here is another example using Expo AuthSession

`import React from 'react';
import { View, StyleSheet, Button } from 'react-native';
import { Auth } from 'aws-amplify';
import { StorageHelper } from '@aws-amplify/core';
import { AuthSession } from 'expo';
import { Buffer } from 'buffer';

const storage = new StorageHelper().getStorage();

const authData = {
ClientId: 'your_app_client_id',
AppWebDomain: 'https://something.auth.us-east-2.amazoncognito.com',
RedirectUriSignIn: 'myapp://',
IdentityProvider: 'Facebook',
};

Auth.configure({
storage: storage
});

export const decodePayload = (jwtToken) => {
const payload = jwtToken.split('.')[1];
try {
return JSON.parse(Buffer.from(payload, 'base64').toString('utf8'));
} catch (err) {
return {};
}
};

export const calculateClockDrift = (iatAccessToken, iatIdToken) => {
const now = Math.floor(new Date() / 1000);
const iat = Math.min(iatAccessToken, iatIdToken);
return now - iat;
};

export class Login extends React.Component {

getTokenByCode = (code) => {
    const details = {
        grant_type: "authorization_code",
        code,
        client_id: authData.ClientId,
        redirect_uri: authData.RedirectUriSignIn
    };
    const formBody = Object.keys(details)
        .map(
            key => `${encodeURIComponent(key)}=${encodeURIComponent(details[key])}`
        )
        .join("&");

    fetch(
        authData.AppWebDomain+"/oauth2/token",
        {
            method: "POST",
            headers: {
                "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
            },
            body: formBody
        }
    )
    .then(res => {
        res.json().then(function(data) {

            const idTokenData = decodePayload(data['id_token']);
            const accessTokenData = decodePayload(data['access_token']);

            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.LastAuthUser', idTokenData['cognito:username']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.idToken', data['id_token']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.accessToken', data['access_token']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.refreshToken', data['refresh_token']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.clockDrift', ''+calculateClockDrift(accessTokenData['iat'], idTokenData['iat'])+'');

            Auth.currentUserInfo()
                .then((res) => {
                    console.log(res);
                    alert('User signed in'+'\n'+'Check the logs');
                })
                .catch((res) => {
                    console.log(res);
                });
        });
    })
    .catch(error => {
        console.error(error);
    });
};

_handlePressAsync = async () => {
    let redirectUrl = authData.RedirectUriSignIn;
    console.log(redirectUrl);
    let result = await AuthSession.startAsync({
        authUrl:
            `${authData.AppWebDomain}/oauth2/authorize?response_type=code` +
            `&client_id=${authData.ClientId}` +
            `&redirect_uri=${encodeURIComponent(redirectUrl)}`,
    });
    if (result.type === 'success') {
        this.getTokenByCode(result.params.code);
    }
    else console.log(result);
};

render() {
    return (
        <View style={styles.main_container}>
            <Button title="Open FB Auth" onPress={this._handlePressAsync} />
        </View>
    );
}

}

const styles = StyleSheet.create({
main_container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
});
`

@engharb
Copy link

engharb commented Dec 20, 2018

@tmjordan I would utilize aws-cognito-auth to store the tokens instead of doing that by myself

// instead of
storage.setItem(.....)
// I would like to create an url text with attached tokens and then pass that url text to
// CognitoAuth auth obj
auth.parseCognitoWebResponse(url);

@tmjordan
Copy link

i tried that, but it didn't work for me

@tmjordan
Copy link

@engharb you can get the redirect url which contains the tokens from the web browser, and then pass it to your method.

@engharb
Copy link

engharb commented Dec 24, 2018

@powerful23 @yuntuowang for simplicity I want to use Cordova-FB or GooglePlus plugins in order to login. And when I logged in successfully I want to pass the i.e FB:IAuthResponse->accessToken to aws oauth2 in order to log me in Cognito-UserPool and fetch the related tokens. Is that somehow possible?!

Where for testing my mobile-app I can not use the webviews (embedded browsers known as “web-views”) in case of Google login. This is a restriction by Google itself "https://developers.googleblog.com/2016/08/modernizing-oauth-interactions-in-native-apps.html".

Is there a way for more digging in knowing the auth behavior betweet AWS-Auth-Server, Cgnito-UserPool, and Fb_provider?

It would be helpful to know i.e the redirect urls...

@sis-dk
Copy link

sis-dk commented Feb 13, 2019

Switch to firebase auth, step up OpenID with AWS cognito identity pools and aws appsync. Took me 30 minutes vs weeks of this.

Sent from my iPhone
On Aug 5, 2018, at 8:17 AM, Leonardo Rodriguez @.***> wrote: Anyone got a solution to this? I was trying the same thing. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

Hey could you please tell me how you did it? I've configured identity pool to use my firebase auth. In my app now how do i initialize Amplify Storage by passing the token from firebase to it?

@tmjordan
Copy link

@powerful23 Please, how to use the new function to set session manually. I installed the beta version of amplify, but i can't find the new function.
Thanks

@undefobj
Copy link
Contributor

Hello everyone. We have been tracking this issue and working on solutions. The root use case seems to be making the OAuth flow easier, not only with React Native but in general. Setting the session manually appears to be an effect of the root problem. To this there are two things I wanted to update this issue and get some feedback on:

  1. On React Native we are in the final stages of releasing a new HOC that will work with React Native, including the latest native bindings that will be compatible with all of the OAuth specs and app store submission policies (this is a tricky space and is what has taken a while for us to comprehensively address). We are trying to get this out in the next week and you can see a version of the PR (which will be tweaked a little soon) here: feat(aws-amplify-react-native): Add withOAuth HOC for Cognito Hosted UI #2665
  2. Generally we want to give a better OAuth and federation experience, including doing some of the things mentioned in this thread like PKCE. We have an RFC for this work listed here that if you have time it would be great if you could comment on it: RFC: Auth Enhancements - Easier Federation with Cognito User Pools and Hosted UI #2716

We're looking forward to your feedback and thank you for being patient while we work on this issue.

@undefobj
Copy link
Contributor

undefobj commented Mar 5, 2019

Hello everyone, we have released the new HOC for React Native with the OAuth process of the Cognito Hosted UI (e.g. #1 above). Please see the instructions here: https://aws-amplify.github.io/docs/js/authentication#launching-the-hosted-ui-in-react-native

@epicfaace
Copy link
Contributor

@undefobj thanks for the update. However, I still need the functionality to set current credentials manually. I am storing my JWT in a cookie and sharing the token between multiple sites, so that is my use case.

@Xander567
Copy link

Xander567 commented May 29, 2019

Hey,
We could definitely do with something like this, so i'm putting my name down too. My user case is as follows:
We have multiple cognito user pools and one login location. A lambda function takes the username and password, authenticates the user and returns the tokens (id, access, refresh). We need to tell the amplify front end that the user is logged in with the credentials from the function. Amplify could then handle the logout and token refresh for us.

Is there anyway of tricking amplify into thinking it's authenticated with a token? i see that getCurrentSession() returns an object that contains the tokens, but no way to setCurrentSession()?

I'm using amazon-cognito-identity-js in the lambda function, which is what amplify uses. I can even returned an authenticated CognitoUser object, but i see no way of setting it on the front end.

@tmjordan
Copy link

@Xander567 here's what i did and it'w working perfectly for me until now. You just have to set the tokens manually, and amplify will just use them with no problems. You can login or logout and the tokens are refreshed automatically.

storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.LastAuthUser', idTokenData['cognito:username']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.idToken', data['id_token']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.accessToken', data['access_token']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.refreshToken', data['refresh_token']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.clockDrift', ''+calculateClockDrift(accessTokenData['iat'], idTokenData['iat'])+'');

@tmjordan
Copy link

you can see the whole code in my previous comments

@Vahn84
Copy link

Vahn84 commented Jul 31, 2019

@powerful23

Has this ever been released?

I'm on react native and i need to login to my user pool via federatedSignIn (Google Provider). The problem is that every 1 hour the token expires and users are forced to login again through the hosted ui. I really need the ability to silently refresh the token and keep the user logged in.

I'm trying to refresh the token myself like this

  let response = await fetch("https://cognito-idp." + env.REACT_APP_BASE_REGION + ".amazonaws.com/", {
                headers: {
                    "X-Amz-Target": "AWSCognitoIdentityProviderService.InitiateAuth",
                    "Content-Type": "application/x-amz-json-1.1",
                },
                mode: 'cors',
                method: 'POST',
                body: JSON.stringify({
                    ClientId: env.REACT_APP_WEB_CLIENT_ID,
                    AuthFlow: 'REFRESH_TOKEN_AUTH',
                    AuthParameters: {
                        REFRESH_TOKEN: token,
                    }
                })
            })

but i don't know how to set the "currentAuthenticatedUser" after that

@genestd
Copy link

genestd commented Sep 2, 2019

@powerful23 I also have this requirement for my project. It's an existing production app where I built my own authentication module with amazon-cognito-identity-js. I would now like to add Analytics from Amplify. It seems like Analytics needs the Auth module to have the credentials to work properly, and I would like to pass the credentials from my login (or refresh) code to the Auth module to let it know that the user is logged in.

I don't see this PR in the current beta release: 1.1.24-beta.10. Can you comment on the status?

@Steinliiippp
Copy link

Is there any progress?

@polson
Copy link

polson commented Mar 29, 2020

Also wondering if there is any way to do this

@matamicen
Copy link

@powerful23 how are you?
Any progress? or any idea to pass the Cognito Mobile credentials (RN) of a user session to a WebView (React.Js)?

Thanks as always!

@MichaelDM
Copy link

@Xander567 here's what i did and it'w working perfectly for me until now. You just have to set the tokens manually, and amplify will just use them with no problems. You can login or logout and the tokens are refreshed automatically.

storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.LastAuthUser', idTokenData['cognito:username']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.idToken', data['id_token']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.accessToken', data['access_token']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.refreshToken', data['refresh_token']);
            storage.setItem('CognitoIdentityServiceProvider.'+authData.ClientId+'.'+idTokenData['cognito:username']+'.clockDrift', ''+calculateClockDrift(accessTokenData['iat'], idTokenData['iat'])+'');

Thank you so much @Xander567, this proved to be wonderful advice!

Implementation detail for others in my case. I'm switching between multiple subdomains with the same authenticated user. For the authentication to work by coping the Cognito storage object (value in localstorage), I had to set bypassCache to true.

Auth.currentAuthenticatedUser({
  bypassCache: true // If set to true, this call will send a request to Cognito to get the latest user data
})

@ericclemmons
Copy link
Contributor

I've been experimenting with this myself, and Amplify.configure({ storage }) is the best mechanism for customizing where credentials are stored and how they are set:

https://docs.amplify.aws/lib/auth/manageusers/q/platform/js#managing-security-tokens

I will note that there is a great deal of reliance on the Credentials flow (especially with refreshing), so your implementation (e.g. Storage.put) will have to be more resilient to errors that will otherwise fail.

In short, yes, it's possible, but there are more edge-cases to be worked around when working "off the rails".

@mkozjak
Copy link

mkozjak commented Nov 13, 2020

@ericclemmons what is the alternative to the approach you described?

@github-actions
Copy link

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels or Discussions for those types of questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Auth Related to Auth components/category feature-request Request a new feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.