signing in with custom token doesn't pass the user details - javascript

I am using signInWithCustomToken() after initiating it on the server.
async function signinWithToken(data, sendResponse) {
const { token } = data;
console.log(token);
signInWithCustomToken(auth, token)
.then((user) => {
console.log(user);
sendResponse({ success: true, user });
})
.catch((err) => {
sendResponse({ success: false, message: err.message
});
});
}
The problem is that the user object returned doesn't include the user details like displayName, email, etc...
Is there something I could do about it?

A custom token only contains the properties/claims that you put into it. Firebase doesn't add any information to the custom token, so if you find certain values missing, it's because your code didn't add them while minting the token.
Also see the Firebase documentation on minting a custom token using the Admin SDK.

The signInWithCustomToken() method returns a Promise which resolves with a UserCredential and not a User.
So you need to do as follows:
async function signinWithToken(data, sendResponse) {
const { token } = data;
console.log(token);
signInWithCustomToken(auth, token)
.then((userCredential) => {
console.log(userCredential.user);
//..
})

Related

userSession is null after Auth.signUp with "autoSignIn" enabled (AWS Cognito)

I need to get the jwtToken from the Auth.signUp. Is this possible if i enable autoSignIn:{enabled:true}?
const signUp = async () => {
await Auth.signUp({
username: email,
password,
attributes: {
email, // optional
name,
},
autoSignIn:{
enabled: true
}
})
.then((data) => {
console.log(data.user); //user.signInUserSession is null
})
.catch((err) => {
if (err.message) {
setInvalidMessage(err.message);
}
console.log(err);
});
await Auth.currentAuthenticatedUser()
.then(user =>{
console.log(user)
})
.catch(error => {
console.log(error) //"User is not authenticated"
})
};
I call I want the jwttoken from the userSession data for conditional rendering and I store the token in my router.js. The response object from Auth.signUp contains a CognitoUser which has a signInUserSession value but its's null.
EDIT: Tried to call Auth.currentAuthenticatedUser() after but yields an error that user is not authenticated. But when i restart my app, the user will be authenticated. I still cant authenticate user on the same app "instance"
import { Auth, Hub } from 'aws-amplify';
const listener = (data) => {
switch (data.payload.event) {
case 'autoSignIn':
console.log('auto sign in successful');
console.log(data.payload) //returns user data including session and tokens.
//other logic with user data
break;
}
};
Above is the code to initalize the Hub listener provided by amplify api. Ater user presses sign up, I called to get user session data when user is automatically signed in.
Hub.listen('auth', listener)

How to prevent Firebase Cloud Function from crashing and how to send error message as response?

I've created a simple createUser function which is executed on call. I have one problem though. The function is crashing when the user is trying to register with an already existing email. I mean, it's ok, since no one wants to have 2 users with the same email address but I want to prevent crushing function, instead, I want to send an error message as a response.
export const createUserTest = functions.https.onCall((data, context) => {
const {email, password} = data;
return new Promise((resolve, reject)=>{
try{
admin
.auth()
.createUser({
email: email,
emailVerified: false,
password: password,
disabled: false,
})
.then((user) => {
resolve({
result: 'success',
user: user,
}) ;
})
.catch((error) => {
reject(error) ;
});
}catch(error) {
reject (error)
}
})
});
I tried to put the function in to try/catch block but it didn't help. Do you have an idea of how I can achieve my goal?
As explained in the doc for Callable Cloud Functions, "to ensure the client gets useful error details, return errors from a callable by throwing (or returning a Promise rejected with) an instance of functions.https.HttpsError".
The error has a code attribute that can be one of the values listed here. In your case, the most appropriate seems to be already-exists.
On, the other hand, you'll find here the Admin SDK Authentication errors list and you'll see that in case the provided email is already in use by an existing user the error code is auth/email-already-exists.
So you can adapt your code as follows:
export const createUserTest = functions.https.onCall((data, context) => {
const { email, password } = data;
return admin
.auth()
.createUser({
email: email,
emailVerified: false,
password: password,
disabled: false,
})
.then((user) => {
return {
result: 'success',
user: user,
}
})
.catch((error) => {
if (error.code === 'auth/email-already-exists') {
throw new functions.https.HttpsError('already-exists', 'The provided email is already in use by an existing user');
} else {
throw new functions.https.HttpsError('...other code....', '...');
// If an error other than HttpsError is thrown, your client instead receives an error with the message INTERNAL and the code internal.
}
});
});
See here in the doc, how to handle errors on the client side. If error.code == 'already-exists' you know that it's because the email is already in use.

Where to put API session auth token in SDK request methods?

I am using the ConnectyCube React Native SDK and have obtained an app auth token using their API. This token is required when making further requests - for example when logging in as a user. Their documentation says:
Upgrade session token (user login)
If you have an application session token, you can upgrade it to a user session by calling login method:
var userCredentials = {login: 'cubeuser', password: 'awesomepwd'};
ConnectyCube.login(userCredentials, function(error, user) {
});
The problem is it that when I use this method, I get an error in response saying 'Token is required'.
If I were interfacing with a REST API, I would put the token in the header of the request, but obviously in this instance I can't. So the question is, where do I put the token? I have it, the documentation just doesn't tell you how to use it! Any help appreciated.
Ok I came up with a fix. First of all I just tried passing the auth token in to the userCredntials object in the same way as in the documentation for social auth, that is absent from the description in my above code snippet taken from their docs.
Then I Promisified the API calls from within useEffect inside an async function to make sure everything was happening in the right order, and it works:
export default function App() {
const createAppSession = () => {
return new Promise((resolve, reject) => {
ConnectyCube.createSession((error, session) => {
!error
? resolve(session.token)
: reject(error, '=====1=====');
});
})
}
const loginUser = (credentials) => {
return new Promise((resolve, reject) => {
ConnectyCube.login(credentials, ((error, user) => {
!error
? resolve(user)
: reject(error, '=====2=====');
}));
})
}
useEffect(() => {
const ccFunc = async () => {
ConnectyCube.init(...config)
const appSessionToken = await createAppSession();
const userCredentials = { login: 'xxxxx', password: 'xxxxxxx', keys: { token: appSessionToken } };
const user = await loginUser(userCredentials);
console.log(user);
}
ccFunc()
}, []);
Hope it works....
please implement it by yourself...just take an understanding from code below.
code says: send the username and password to api...if all ok then authenticate else throw error ...if all ok..then store the returned token is asyncStorage...you can create the storage by any name you like...and use the token eveywhere in your app.
SignInUser = async () => {
this.setState({
username: this.state.username,
password:this.state.password,
})
if(this.state.username && this.state.password !== null){
try{
this.setState({
loading:true
})
const response = await fetch('YOUR API', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password
})
});
var promiseResponse = await response.json()
console.log(promiseResponse.token);
try {
await AsyncStorage.setItem('STORE_YOUR_LOGIN_TOKEN_HERE', JSON.stringify(promiseResponse.token));
console.log('Token Stored In Async Storage');
let tokenFromAsync = await AsyncStorage.getItem('STORE_YOUR_LOGIN_TOKEN_HERE');
console.log('Getting Token From Async...')
tokenFromAsync = JSON.parse(tokenFromAsync)
if(tokenFromAsync !== null){
console.log(tokenFromAsync);
this.setState({
loading:false
})
this.props.navigation.navigate('Tabnav');
}
} catch (error) {
// saving error
console.log(`ERROR OCCURED ${error}`)
}
//this.props.navigation.navigate('Tabnav')
} catch(error){
console.log(`COULDN'T SIGN IN ${error}`)
}
} else {
this.setState({
msg:'Invalid Credentials',
label:'red'
});
}
}
This is how i got the login to work in their sample react native app 1. i created a credentials object like this in my custom login function in src>components>AuthScreen>AuthForm.js
var credentials = {id:'',login: this.state.login,password: this.state.password}
2.I used their _signIn(credentials) function and set the 'id' attribute of my credentials object after their UserService.signin(credentials) resolved with a user object. (the resolved user object contained the logged-in user's id i.e user.id). Then it worked. This is how the code looked for the signin after the little tweak.
loginUser() { //my custom signin function
var credentials = {id:'',login: this.state.login,password: this.state.password} //my credentials object
this._signIn(credentials)
}
_signIn(userCredentials) { //their signin function
this.props.userIsLogging(true);
UserService.signin(userCredentials)
.then((user) => {
userCredentials.id = user.id //setting id of my credentials object after promise resolved
ChatService.connect(userCredentials) //using my credentials object with id value set
.then((contacts) => {
console.warn(contacts)
this.props.userLogin(user);
this.props.userIsLogging(false);
Actions.videochat(); //login worked
})
.catch(e => {
this.props.userIsLogging(false);
alert(`Error.\n\n${JSON.stringify(e)}`);
})
})
.catch(e => {
this.props.userIsLogging(false);
alert(`Error.\n\n${JSON.stringify(e)}`);
})
}

can't update user's email

I am trying to update the email of the current user, I went to documentation and I copied the example code that they are given there,
But nothing worked, this from doc didn't work
var user = firebase.auth().currentUser;
user.updateEmail("newemail#example.com").then(function() {
console.log('success')
}).catch(function(error) {
console.log('failed')
});
I have also tried :
try {
await user.updateEmail('test#test.com').then(function() {
console.log('success')
}).catch(function(error) {
handleErrors(dispatch, error.message);
});
} catch(e) {
handleErrors(dispatch, e.message);
}
could you help to solve this issue?
update :
sorry i didn't include the exact error that come out in the console , here is the error :
This operation is sensitive and requires recent authentication. Log in
again before retrying this request.
2)
I should add that I am using asyncstorage of react native , and I store that Item( profile of user => email , name , ect..) in reduxPersist
that how my login code is :
export const login = ( email, password ) => {
return async (dispatch) => {
dispatch({ type: ATTEMPTING });
try {
await firebase.auth().signInWithEmailAndPassword(email, password)
.then(resp => handleLoginSuccess(dispatch, resp.uid,resp.name,email))
.catch(error => handleErrorLogin(dispatch, error.message));
}catch(e){
handleErrorLogin(dispatch, e.message);
}
};
};
const handleLoginSuccess = async(dispatch , userId,name,email) => {
try{
const profile = { userId, name, email };
await AsyncStorage.setItem('userProfile', JSON.stringify(profile));
dispatch({ type: LOGIN_SUCCESS, payload: profile });
}catch(e){
alert(e.message);
}
}
The error message is telling you that there is no user logged in at the time you call updateEmail. The SDK doesn't know which user you're trying to modify. You'll need to wait until the login is fully complete before calling that method.
Note that all of the Firebase APIs are asynchronous, so you'll need to make use of their returned promises to make sure the order of calls is valid.

Angular 4 & Passport API authentication

I'm building a web app with the MEAN Stack. What I am trying to achieve is that when the user logs in his user information get fetched by Angular from my REST API. I set up the API route http://localhost:3000/api/user/profile which should respond with json including the user object.
router.get('/user/profile', function(req, res, next){
//console.log(req);
if(req.user === undefined){
res.json({
success: false,
msg: 'Unautorized'
});
} else {
res.json({
success: true,
user: {
id: req.user.steam.id,
name: req.user.steam.name,
avatar: req.user.steam.avatar,
avatarmedium: req.user.steam.avatarmedium,
avatarfull: req.user.steam.avatarfull
}
});
}
});
When the user logs in Angular start a GET-Request:
ngOnInit() {
this.authService.getProfile().subscribe(profile => {
this.user = profile.user;
console.log(profile);
},
err => {
console.log(err);
return false;
});
}
getProfile():
getProfile(){
return this.http.get('http://localhost:3000/api/user/profile')
.map(res => res.json());
}
When I load up my site, log in, and go to the profile page the returned object contains success: false and the message 'Unauthorized' instead of the user object. Why is this happening?
I completely redesigned my approach. I implemented json web token which now sends a token (containing all user data) to the user through a url parameter once he signs in.

Categories

Resources