I'm trying to authenticate user using facebook through firebase:
Login
but getting [object Object] error:
Loginfailed
My code for login is:
facebookLogin(): void {
this.fb.login(['email']).then( (response) => {
const facebookCredential = firebase.auth.FacebookAuthProvider
.credential(response.authResponse.accessToken);
firebase.auth().signInWithCredential(facebookCredential)
.then((success) => {
alert("Firebase success: ");
this.userProfile = success;
})
.catch((error) => {
alert(error);
});
}).catch((error) => {alert(error); });
}
All of the documentation I see requests both the email and the public_profile in the login function, perhaps this is the error.
this.fb.login(['email', 'public_profile']).then( (response) => {
Related
Here is my code
import { Auth } from 'aws-amplify';
function forgotPassword() {
Auth.forgotPassword(phoneNumber)
.then((data) => {
console.log(data);
})
.catch((err) => {
console.log(err);
});
}
function forgotPasswordSubmit() {
Auth.forgotPasswordSubmit(
phoneNumber,
code,
password
)
.then((data) => {
console.log(data);
})
.catch((err) => {
console.log(err);
});
}
I am using Auth.forgotPassword from amplify sdk. When I submit phone number that is not existed in Cognito, Auth.forgotPassword function will not throw any error. I wonder if this function will check user existence? If not, any other method I can use to check it?
Thanks.
Can I get the phone number of a user using People API? If not is there any other API that I can use to get a user's phone number? I can't seem to find a anything on that.
below code is what I've tried
First I signIn using auth2.
useEffect(() => {
console.log("window: ", window);
window.gapi.load("client:auth2", initClient);
}, []);
const initClient = () => {
window.gapi.auth2.init({
client_id: "CLIENT_ID",
});
authenticate().then(loadClient);
};
const authenticate = () => {
return window.gapi.auth2
.getAuthInstance()
.signIn({
scope:
"https://www.googleapis.com/auth/contacts
https://www.googleapis.com/auth/contacts.readonly
https://www.googleapis.com/auth/directory.readonly
https://www.googleapis.com/auth/user.addresses.read
https://www.googleapis.com/auth/user.birthday.read
https://www.googleapis.com/auth/user.emails.read
https://www.googleapis.com/auth/user.gender.read
https://www.googleapis.com/auth/user.organization.read
https://www.googleapis.com/auth/user.phonenumbers.read
https://www.googleapis.com/auth/userinfo.email
https://www.googleapis.com/auth/userinfo.profile",
})
.then(
(response) => {
console.log("sign in successful: ", response);
},
(err) => {
console.log("error signing in: ", err);
}
);
};
Then I load the client using.
const loadClient = () => {
window.gapi.client.setApiKey("API_KEY");
return window.gapi.client
.load("https://people.googleapis.com/$discovery/rest?version=v1")
.then(
() => {
console.log("GAPI client loaded for api");
},
(err) => {
console.log("error loading GAPI client for api: ", err);
}
);
};
Finally I execute this request to people api to get the info.
I can get the name and email address of the logged in user but I am not getting phone number.
const execute = () => {
return window.gapi.client.people.people
.get({
resourceName: "people/me",
personFields: "names,emailAddresses,phoneNumbers",
})
.then(
(response) => {
console.log("people response: ", response);
},
(err) => {
console.log("people err: ", err);
}
);
};
You will need the user.phonenumbers scope. From the OAuth 2.0 Scopes section:
View your/current user phone numbers
https://www.googleapis.com/auth/user.phonenumbers.read
You can then use people.get("people/me") with personFields="phoneNumbers" to get a Person instance with the phoneNumbers field populated.
[This is a Vue app, using Vuex, created with vue-cli, using mocha, chai, karma, sinon]
I'm trying to create tests for my vuex state and I DON'T want to use a mock -- one of my big goals for these tests is to also test the API that data is coming from.
I am trying to follow the docs for chai-as-promised.
This is a simplification of the vuex action I'm trying to test:
const actions = {
login: (context, payload) => {
context.commit('setFlashMessage', "");
axios.get("https://first-api-call")
.then((response) => {
axios.post("https://second-api-call")
.then((response) => {
router.push({ name: "Home"});
context.commit('setFlashMessage', "Logged in successfully");
context.commit('setLogin', response.data);
});
},
Notice that the login action has two promises and doesn't return anything. The login action does two things: it sets some state and it changes the route.
The example that I've seen that using chai-as-promised expects that the promise is returned. That is:
var result = systemUnderTest();
return expect(result).to.eventually.equal(blah);
But in my case, login() doesn't return anything, and I'm not sure what I would return if it did.
This is what I have so far:
import store from '#/src/store/store'
describe('login', () => {
it('bad input', () => {
store.login({ username: "abcd", password: ""});
// What is the test I should use?
}
}
I would return the login response message and make two tests. One to make sure that invalid credentials return a failure message and one to make sure that valid credentials login successfully
My co-worker and I came up with the solution:
The vuex action needs to return the promise, and they can be chained together:
login: (context, payload) => {
context.commit('setFlashMessage', "");
return axios.get("https://first-api-call")
.then((response) => {
return axios.post("https://second-api-call")
})
.then((response) => {
// etc...
router.push({ name: "Home"});
context.commit('setFlashMessage', "Logged in successfully");
context.commit('setLogin', response.data);
return {status: "success"};
});
},
Then we didn't need chai-as-promised because the test looks like this:
it('bad password', () => {
const result = store.dispatch("login", { username: userName, password: password + "bad" });
return result.then((response) => {
expect(response).to.deep.equal({ status: "failed"});
store.getters.getFlashMessage.should.equal("Error logging in");
});
});
I am finishing up test for my actions test and am running into one test failing. The weird thing what is causing it to fail passes in other test.
import { browserHistory } from 'react-router';
//Passing action
export function signinUser({ email, password }) {
return function(dispatch) {
// Submit email/password to the server
return axios.post(`${ROOT_URL}/signin`, { email, password })
.then(response => {
// If request is good...
// - Update state to indicate user is authenticated
dispatch({ type: AUTH_USER });
// - Save the JWT token
localStorage.setItem('token', response.data.token);
localStorage.setItem('refreshToken', response.data.refreshToken);
// - redirect to the route '/feature'
browserHistory.push('/feature');
})
.catch(() => {
// If request is bad...
// - Show an error to the user
dispatch(authError('Bad Login Info'));
});
}
}
//failing action
export function confirmationEmail(token){
return function(dispatch) {
return axios.post(`${ROOT_URL}/confirmation`, { token })
.then(response => {
//dispatch(emailWasSent(response.data.return_msg));
// If request is good...
// - Update state to indicate user is authenticated
dispatch({ type: AUTH_USER });
// - Save the JWT token
localStorage.setItem('token', response.data.token);
localStorage.setItem('refreshToken', response.data.refreshToken);
// - redirect to the route '/feature'
browserHistory.push('/feature');
})
.catch(response => {
console.log(response)
dispatch(authError(response.data.error));});
}
}
The 2 methods are almost identical past the params passed. Both test are almost exactly the same also
describe('signinUser', () => {
it('has the correct type and payload', () => {
var scope = nock(ROOT_URL).post('/signin',function(body) {return { email: 'test#gmail.com', password: "test"}}).reply(200,{ token: "majorbs123" , refreshToken: "bs123"});
const store = mockStore({});
return store.dispatch(actions.signinUser('test#gmail.com',"test")).then(() => {
const act = store.getActions();
const expectedPayload = { type: AUTH_USER }
expect(act[0].type).to.equal(expectedPayload.type);
expect(localStorage.getItem("token")).to.equal("majorbs123");
expect(localStorage.getItem("refreshToken")).to.equal("bs123");
})
});
});
describe('confirmationEmail', () => {
it('has the correct type and payload', () => {
var scope = nock(ROOT_URL).post('/confirmation',function(body) {return { token: 'tokenbs123'}}).reply(200,{ token: "majorbs123" , refreshToken: "bs123"});
const store = mockStore({});
return store.dispatch(actions.confirmationEmail("tokenbs123")).then(() => {
const act = store.getActions();
const expectedPayload = { type: AUTH_USER }
expect(act[0].type).to.equal(expectedPayload.type);
expect(localStorage.getItem("token")).to.equal("majorbs123");
expect(localStorage.getItem("refreshToken")).to.equal("bs123");
})
});
});
The first test for signin passes no problem and the browserHistory.push has no problems. The second test throws this error stack.
SecurityError
at HistoryImpl._sharedPushAndReplaceState (/home/mikewalters015/client/node_modules/jsdom/lib/jsdom/living/window/History-impl.js:87:15)
at HistoryImpl.pushState (/home/mikewalters015/client/node_modules/jsdom/lib/jsdom/living/window/History-impl.js:69:10)
at History.pushState (/home/mikewalters015/client/node_modules/jsdom/lib/jsdom/living/generated/History.js:71:31)
at /home/mikewalters015/client/node_modules/history/lib/BrowserProtocol.js:87:27
at updateLocation (/home/mikewalters015/client/node_modules/history/lib/BrowserProtocol.js:82:3)
at pushLocation (/home/mikewalters015/client/node_modules/history/lib/BrowserProtocol.js:86:10)
at /home/mikewalters015/client/node_modules/history/lib/createHistory.js:117:15
at /home/mikewalters015/client/node_modules/history/lib/createHistory.js:90:9
at next (/home/mikewalters015/client/node_modules/history/lib/AsyncUtils.js:51:7)
at loopAsync (/home/mikewalters015/client/node_modules/history/lib/AsyncUtils.js:55:3)
at confirmTransitionTo (/home/mikewalters015/client/node_modules/history/lib/createHistory.js:80:31)
at transitionTo (/home/mikewalters015/client/node_modules/history/lib/createHistory.js:100:5)
at Object.push (/home/mikewalters015/client/node_modules/history/lib/createHistory.js:131:12)
at Object.push (/home/mikewalters015/client/node_modules/history/lib/useBasename.js:73:22)
at Object.push (/home/mikewalters015/client/node_modules/history/lib/useQueries.js:81:22)
at /home/mikewalters015/client/src/actions/authActions.js:106:2
at process._tickCallback (internal/process/next_tick.js:103:7)
It has thrown me for a loop cause the code is so similar and the line throwing the issue the react-router push method is used in other methods also and produces no problems.
I'm using ember-simple-auth and a custom authenticator for an HTTP basic login with CSRF protection. Everything is working fine except sometimes my restore method resolves when it should be failing, like when the session expires.
When authentication succeeds I resolve with the csrf token, but then when the token or session expires and I refresh the page, the resolve method still succeeds because all I'm doing is checking if the token is still there (not if it's valid). I know this is wrong, so I guess my question would be what is the proper way to handle this? Should I also be resolving with the session id? Should I be sending an AJAX request in the restore method with the stored token to see if it is still valid and returns success? I'm interested in hearing about any other improvements I could make as well.
Here is my authenticator code:
import Ember from 'ember';
import ENV from 'criteria-manager/config/environment';
import Base from 'ember-simple-auth/authenticators/base';
export default Base.extend({
restore(data) {
return new Ember.RSVP.Promise((resolve, reject) => {
if (data.token) {
Ember.$.ajaxSetup({
headers: {
'X-XSRF-TOKEN': data.token
}
});
resolve(data);
}
else {
reject();
}
});
},
authenticate(credentials) {
let csrfToken = this.getCookie('XSRF-TOKEN');
return new Ember.RSVP.Promise((resolve, reject) => {
Ember.$.ajax({
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "Basic " + btoa(credentials.username + ":" + credentials.password));
xhr.setRequestHeader("X-XSRF-TOKEN", csrfToken);
},
url: ENV.host + "/api/users/login",
method: 'POST'
}).done(() => {
//A new CSRF token is issued after login, add it to future AJAX requests
Ember.$.ajaxSetup({
headers: {
'X-XSRF-TOKEN': this.getCookie('XSRF-TOKEN')
}
});
Ember.run(() => {
resolve({
token: this.getCookie('XSRF-TOKEN')
});
});
}).fail((xhr) => {
Ember.run(() => {
if(xhr.status === 0) {
reject("Please check your internet connection!");
}
else if (xhr.status === 401) {
reject("Invalid username and/or password.");
}
else {
reject("Error: Http Status Code " + xhr.status);
}
});
});
});
},
invalidate() {
return new Ember.RSVP.Promise((resolve, reject) => {
let csrfToken = this.getCookie('XSRF-TOKEN');
Ember.$.ajax({
beforeSend: function(xhr) {
xhr.setRequestHeader("X-XSRF-TOKEN", csrfToken);
},
url: ENV.host + '/logout',
method: 'POST'
}).done(() => {
Ember.run(() => {
resolve();
});
}).fail(() => {
Ember.run(() => {
reject();
});
});
});
},
getCookie(name) {
let alLCookies = "; " + document.cookie;
let cookieArray = alLCookies.split("; " + name + "=");
if (cookieArray.length === 2) {
return cookieArray.pop().split(";").shift();
}
}
});
Should I also be resolving with the session id? Should I be sending an
AJAX request in the restore method with the stored token to see if it
is still valid and returns success?
It all depends on your project's needs. In my opinion it's good to check if token is still valid. For example, oauth2-password-grant stores expiring date in session and when restoring simply compares it with current time. You may do this too. Or, if your backend has some token validation endpoint, you may send request to be sure if token is valid.