I have made an API with Laravel. There are three URLs, one to check whether the user is logged in or not (GET), one to log in (POST), and one to log out (GET).
I tried the APIs with Postman, and they work just fine. The order of my trying is: Check, Log in, check again. The results are False, ID#, True - in that order.
Now, I created a simple UI in React with three buttons, each one calls a function that implements the respective AJAX request. When I check the status of the user after logging in, it always returns False. I don't seem to find where the problem is. Can anyone help?
jQuery's AJAX didn't send the cookies by default, so I had to add an option to the AJAX call.
Added
xhrFields: {
withCredentials: true
}
and it worked.
Related
I am hoping some of you can give me the best practice on how to verify my reCaptcha token on the server.
I have a Symfony 6 app with API Platform. I have defined some entities as API Resources, so I can POST data. On the front end I am using Vue with axios to POST to the specific end points.
I would like to verify the reCaptcha token, before the data from my form is posted, and came up with the below 3 options (Not really sure if any of these are the correct way to go about this)
Create a separate end point for reCaptcha, that I post data to and depending on the response run axios post request for form or not.
Create an up mapped property on the entities I want to use reCaptcha with and set a custom validator on this that validates if the response on token is success. I can then send the reCaptcha token as part of the post request.
Create an event listener for PRE_POST and somehow validate there???
I'm not sure if I'm on the right track with any of the above, the documentation I have been able to find is pretty non existent.
I would really appreciate being pointed in the right direction, or perhaps an example of best practice on this with my current set up?
For those of you coming across this with the same issue I solved it with the following steps: (I would still like to know from someone with more knowledge, if this would be considered best practice or if there is a better way).
Added an unmapped field (No #[ORM\Column annotation) to the Symfony entity I was posting data to, called reCaptchaToken. Added the set method to my denormalizationContext group.
Created ReCaptchaConstraint (class extending Constraint) and set validatedBy method to ReCaptchaConstraintValidator::class
Created ReCaptchaConstraintValidator (class extending ConstraintValidator), added HttpClientInterface to constructor and in validate method posted to recaptcha API (details of this end point can be found in reCaptcha documentation) to validate token and score. If validation failed or score too low, added violation.
Back in Symfony entity, added #[ReCaptchaConstraint] annotation to reCaptchaToken field.
Then from front end, created Vue method:
validateCaptcha() {
return new Promise((res) => {
grecaptcha.ready(() => {
grecaptcha.execute('YOUR_SITE_KEY', {action:
'addContact'}).then((token) => {
return res(token);
})
})
})
}
In .then() method of validateCaptcha() add token to my JSON object and posted to API end point normally.
Now if there is an issue with my token or score, I will get a validation violation returned from POST.
Hope this helps someone else struggling.
Using Nuxt 2.15.3, with a Rails backend.
I'm trying to create a Google OAuth workflow in my app, and I'm having some trouble with the steps after getting the access code. Once the user authenticates with Google and gets redirected back with the access code in the URL params, I send a request to my own backend to save the access/refresh tokens in the User model.
NOTE: this google Auth flow is separate from my normal app sign-in/sign-up flow. I'm only using some Google APIs, so this has nothing to do with making a user account via Google OAuth, I'm only requesting access to some APIs in the user's Google account, namely the My Business API.
Now, my backend has a boolean google_authenticated field on the User table which gets set to true if the access/refresh token exists, which automatically gets sent to Nuxt as $auth.user.google_authenticated. This feature works fine, but my problem is that the page where the users get redirected to has a v-if that checks for this google_authenticated flag.
The template looks like this, obviously simplified for the sake of the question
<template>
<div v-if="googleAuthenticated">...</div>
<div v-else><a href="googleapis.com">Authenticate</button></div>
</template>
export default {
data() {
return {
googleAuthenticated: this.$auth.user.googleAuthorized,
};
},
async mounted() {
const accessCode = this.$route.query.code;
await this.$axios
.post("/users/google_oauth", {
access_code: accessCode,
})
.then((response) => {
this.$auth.fetchUser();
});
}
}
So as you can see, what I'm trying to do is to refresh the $auth.user.googleAuthorized automatically on mount when the user gets to the page with the code in the URL params. The problem is that $auth.user doesn't seem to be reactive, and the user needs to either navigate to another page or refresh the current page to get these changes to show up and for the v-if to trigger and to show the other div.
I can see from the dev console that the fetchUser() method does indeed get called, and I can see from the Vuex store that the auth/SET function has been called and that the $auth.user.googleAuthorized flag is set to true as well.
According to the Nuxt Docs, the $auth module is reactive, but I'm failing to see it. What can I do here to make these changes stick properly?
So it turns out it's a race condition (sorta).
What's happening is that once I tell my own API to get the access tokens from Google, that request obviously takes some non-zero amount of time. As such, Vue is waiting to get the 200 from my own API indicating that I've fetched the access token and can continue with using Google APIs.
So basically, by the time Nuxt is calling fetchUser() again, it's actually getting the user without the googleAuthorized flag set to true, because that just happens a tiny bit too slowly. It's not really something noticeable when you're just looking at dev tools though, since everything seems to be happening instantaneously more or less, but the timings are extremely close, which is the reason why it would sometimes work, and other times it wouldn't without a refresh.
When a user changes a dropdown, I need to make an ajax call to an endpoint, that grabs the data and return it as a JSON.
I can do the event stuff with Vue, to make the request, but how do I guarantee that Vue is the requestor?
I can't really put an API key or something in the JS as that can be viewed through source. Someone could also watch the network tab in chrome and replay the requests to retrieve the data.
Unless you want to ask people to login first, there is no way you can do this. There is a HTTP header you can look for that most libraries add for Ajax requests, but that can be faked as well.
You cannot hide any information from the request you are making. It's the server side on which you can make your code strong. To prevent fake request you can use CSRF token, you need to also validate if the user is logged in, you can check session etc. before you send the result to the client.
I'm struggling to make JSONP request using vue-resource. Can anybody provide some working examples demonstrating the proper way of defining jsonp callback, handling the call within Vue component and so on.
Thanks
**EDIT:**For other fellows, let’s clarify the situation a bit. What was the point - I have a non-authenticated user on the site and I wanted to let him do some action that requires authentication (create post e.g.). However, at the very end of creating post I wanted to show him sign-in modal window, let him log in using social oAuth providers and on successful login, let the post being approved and so on. Problem was that this call from the front-end toward different domains (social providers) was blocked (CORS issue) and than I tried to use JSONP to overcome the obstacle. Trying to setup JSONP call had spent a really lot of my time and finally I decided to go with totally different approach:
At the end of the process of creating the post, a cookie is created, caring the info what was the action that was interrupted with all necessary details. After that, a login modal is shown. Whole login process is done from the server side, and at the end, when identity of an user is confirmed, redirect to initial page is made. Further on, cookie is checked and based on the data, interrupted action continues execution successfully since the user is authenticated now.
#bryceadams thanks again for the answer!
How you handle it in your component will depend on your implementation, but typically it's done in a method - like if you had a form and then on submitting the form you called a method that made a JSONP request.
Here's an example call. Note that the important part is the jsonp option where you set the callback. This can vary based on where you're making the request to. Often it will be callback, but in my case I was working with MailChimp where it was c.
var options = {
jsonp: 'c'
}
this.$http.jsonp('https://website.com', options).then(function(data){
console.log(data.json());
}, function(error) {
// handle errors
});
I'm using Ember-Simple-Auth on an Ember-CLI project, and I'm also using the provided ember-simple-auth-devise authenticator that comes with 3.1. I'm able to login and logout successful, but I can't figure out where's the best place to put the callback (or when the promise resolves) upon successfully logging in. I want to be able to use the data returned by my API on my app after logging in. Any suggestions and advice would be highly appreciated! If requested, I can also provide code samples (although I figured it wasn't necessary since what I have implemented thus far is nothing custom).
Thanks!
When the session is authenticated successfully, the sessionAuthenticationSucceeded action is triggered (see http://ember-simple-auth.simplabs.com/ember-simple-auth-api-docs.html#Ember-SimpleAuth-ApplicationRouteMixin-sessionAuthenticationSucceeded, there are also more actions for other events). So that's a good place to react to the session becoming authenticated.
As the authenticator will set all values the server responds with as properties on the session you could also define additional properties that depend on these - see example here (where the account property depends on the accountId property that's read from the server response): https://github.com/simplabs/ember-simple-auth/blob/master/examples/4-authenticated-account.html#L101