const login: SubmitHandler<ILoginValues> = async ({email, password}) => {
try {
const res = await fetch(`${config.apiUrl}/api/login`, {
method: 'POST',
body: JSON.stringify({
email,
password,
}),
});
if (res.ok) {
await setGenericPassword(email, password, CREDENTIALS_STORAGE_OPTIONS);
setUser({isLoggedIn: true, hasSessionExpired: false});
}
} catch (error) {
toast.setToast({message: 'Login failed', visible: true});
}
};
I am creating a login flow in react native using java spring rest api. My Api is running at address http://localhost:8082/api/v1/users how can I get the data from client side using fetch in React native and also store the JWT token in client side.
You can perform the login request when the form is submitted. Than wait for the response and save the jwt in local storage. Than login the user into the logged in ui.
const form = document.getElementById("form-id")
form.addEventListener("submit", async (e) =>{
e.prevetDefault() your code })
Related
After a long discussion with ChatGPT, I managed to write code that redirects the user to the Stripe payment page and then captures an event when the transaction is successfully completed.
The problem is that my fetch request has already received a response from the /checkout endpoint and is not waiting for a response from /webhook. And I would like my API to return a properly generated response after successfully finalizing the transaction. What am I doing wrong?
First, I send a request to the /checkout endpoint, which takes care of generating the payment link and sending it back:
fetch('http://localhost:3001/checkout', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
items: [
{
id: 0,
},
],
}),
})
.then((res) => {
if (res.ok) return res.json();
return res.json().then((e) => console.error(e));
})
.then(({url}) => {
console.log(url);
window.location = url;
})
.catch((e) => {
console.log(e);
});
This code when I press the button redirects me to the Stripe payment page.
Endpoint /checkout:
app.post('/checkout', async (req, res) => {
try {
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: req.body.items.map(({id}) => {
const storeItem = storeItems.get(id);
return {
price_data: {
currency: 'pln',
product_data: {
name: storeItem.name,
},
unit_amount: storeItem.priceInCents,
},
quantity: 1,
};
}),
mode: 'payment',
success_url: `${process.env.CLIENT_URL}/success.html`,
cancel_url: `${process.env.CLIENT_URL}/cancel.html`,
});
console.log(session.url);
res.json({url: session.url});
} catch (e) {
// If there is an error send it to the client
console.log(e.message);
res.status(500).json({error: e.message});
}
});
I connected StripeCLI to my server using stripe listen --forward-to localhost:3001/webhook. Now I can capture the successful transaction event using the /webhook endpoint, but I have no way to return The transaction was successful to the client:
app.post('/webhook', (req, res) => {
const event = req.body;
if (event.type === 'checkout.session.completed') {
res.send('The transaction was successful');
}
});
After the suceesful payment the customer should be redirected back to your website. Where you can create success page.
success_url: `${process.env.CLIENT_URL}/success.html`,
If you want to get some data back from the Strapi after the paymant is successful page you can add this
success_url: `${process.env.CLIENT_URL}/success.html?&session_id={CHECKOUT_SESSION_ID}`
At the succes page you just deconstruct the data. And do whatever you want with them :)
If you deconstruct the object for example like this: (Next.js)
const stripe = require("stripe")(`${process.env.STRIPE_SECRET_KEY}`);
export async function getServerSideProps(params) {
const order = await stripe.checkout.sessions.retrieve(
params.query.session_id,
{
expand: ["line_items"],
},
);
const shippingRate = await stripe.shippingRates.retrieve(
"shr_1MJv",
);
return { props: { order, shippingRate } };
}
export default function Success({ order, shippingRate }) {
const route = useRouter();
Yo can log out the whole object to see whats inside
console.log(order);
If the payment was sucessfull you should get in prop variable: payment_status: "paid"
Stripe will automatically redirect the client to the success_url that you specified when you created a Stripe session.
You can use the webhook for saving the order in the database for example, but not to redirect the client.
i have one project in spring boot where i have created one API login.where i am sending user name and password with this API .if data is present in database it is returning login successfully if not then it is returning login fail.in react i have to text filed and i am storing that data.now i want to call login API in react with saved text field value and if login successfully then i want to save that response or that returned value in react it may be login successfully or all user details or show that response in react.please anyone help
Use Error handling function
try{
//Call your API here
}
catch(){
//Error handles here
}
finally{
//Executes anyway
}
You have to save your response in state then show it on frontend
import axios from 'axios';
const [loginData, setLoginData] = useState([]);
const onSubmit = async (e) => {
e.preventDefault();
try {
const requestBody = {
emailAddress: email,
password: password,
}
axios.post(`${config.url.API_URL}${BASE_URL.Auth_BASE_URL}/login`, requestBody)
.then(response => {
if (response) {
setLoginData(response);
console.log("Login success");
} else {
console.error("Login fail");
}
}).catch(function (error) {
console.log(error);
});
} catch (err) {
console.log(err);
}
}
I am using Laravel API as a backend for my react-native application. I want to get all the logged in user's data from the users table when he logs in.
I've tried several things but nothing has worked so far.
Here is my code:
Laravel api.php:
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});// i also tried this code.
Route::get('/user', function (Request $request) {
return $request->user();
});
ProfileScreen.js
const [user, setUser] = useState({});
const getUser = async () => {
try {
const token = await AsyncStorage.getItem('auth_token');
axios.get("/api/user").then(res => {
console.log(res.data)//this is logging nothing.
}).catch(e => console.log(e));
} catch (e) {
console.log('error' + e);
}
};
useEffect(() => {
getUser();
});
auth()->user() is a global helper, Auth::user() is a support facade,
and $request->user() uses http.
You can use any of them. For a quick test, try
Route::get('/test', function() {
return auth()->user();
})->middleware('auth:sanctum');
Be sure to send your token in a header like so:
Authorization: Bearer UserTokenHere
Hi I am using express for backend authentication and these are my sign in functions/controllers on the front end.
export const signInUser = async credentials => {
console.log('this is for the signInUser', credentials)
try {
const resp = await api.post('/sign-in', credentials)
localStorage.setItem('token', resp.data.token)
return resp.data
} catch (error) {
throw error
}
}
onSignIn = event => {
event.preventDefault()
const { history, setUser } = this.props
signInUser(this.state)
.then(res => setUser(res.user))
.then(() => history.push('/Home'))
.catch(error => {
console.error(error)
this.setState({
loginUsername: '',
loginPassword: '',
})
})
}
setUser = user => this.setState({ user })
and this is my sign in controller on the backend
const signIn = async (req, res) => {
try {
console.log('hello' ,req.body);
const { loginUsername, username, loginPassword } = req.body;
const user = await User.findOne({
where: {
username: loginUsername
}
});
console.log('this is the user', user)
if (await bcrypt.compare(loginPassword, user.dataValues.password_digest)) {
const payload = {
id: user.id,
username: user.username,
password: user.password
};
const token = jwt.sign(payload, TOKEN_KEY);
return res.status(201).json({ user, token });
} else {
res.status(401).send("Username or Password is invalid- try again.");
}
} catch (error) {
return res.status(500).json({ error: error.message });
}
};
The issue is the state of the user doesn't persist on refresh but I still have the json webtoken in my local storage and this is an issue when I make post requests and even signing up since I am redirecting to the home page and losing the user state. Any help would be appreciated!
From your tags, I noticed that you are using React, so the solution is simple!
you can have an GlobalAuthManager context for your application that would wrap all the components at the most higher level! after <React.strictMode> like below:
<React.StrictMode>
<GlobalAuthManager.Provider value={{authData}}>
<App />
</GlobalAuthManager.Provider>
</React.StrictMode>
As you might guess, this would be a context! that would provide you your user data to all your components!
The Pattern:
1. Store token:
when your user logins to your app, you would receive a token ( in your response or in response header ), you need to store the token value in localstorage, or more better in cookie storage (there are a lot of articles about it why), one is here.
2. have a /getUserData endpoint in backend:
you need to have a /getUserData endpoint in backend to retrive your user data based on token
3. call /getUserData in app mount:
before every thing in your app, you need to call this endpoint if you find token in localstorage or cookie storage. so if you run this in your componnetDidMount or useEffect(() => { ... }, []), that would work!
4. store your user data and state in context:
after you've called the /getUserData and if you had a valid token(i mean not expired token or not interrupted and edited token) , you will get you user data and what you need to do is that you need to store this in your GlobalAuthManager and provide that in to your Global App component!
after that you have your user data available to you that you can decide to show login or sign up button in your Navbar or disable/enable comment section for example based on your user data!
Wrap up:
So the key is that you have to have a GlobalAuthManager for only one purpose, that before every thing it runs in the top level in your app and gets you your user data based on provided token from localstorage or cookie storage!
after that you can manage your app state based on that your user is logged in or not!
I'm using nuxt to develop a client for my laravel project.
In the login.vue component I have the following JS code
import Form from 'vform'
export default {
head () {
return { title: this.$t('login') }
},
data: () => ({
form: new Form({
email: '',
password: ''
}),
remember: false
}),
methods: {
async login () {
let data;
// Submit the form.
try {
const response = await this.form.post('/api/login');
data = response.data;
} catch (e) {
return;
}
// Save the token.
this.$store.dispatch('auth/saveToken', {
token: data.token,
remember: this.remember
});
// Fetch the user.
await this.$store.dispatch('auth/fetchUser');
// Redirect home.
this.$router.push({ name: 'home' })
}
}
}
If I try to submit the login form with wrong email and password values I see an error message in a browser console.
For example:
POST http://laravel.local/api/login 422 (Unprocessable Entity)
Please note that I'm using try catch that catches all errors on the following call.
const response = await this.form.post('/api/login');
Is this really issue with async/await usage?
How can I get rid of that error in the browser console?
If you need some more info from me do not hesitate to ask it.