How can I submit to custom credentials? - reactjs

Hello I have the following next auth configuration:
import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials"
export default NextAuth({
providers: [
CredentialsProvider({
name:'Login',
credentials: {
email: { label: "Email", type: "text" },
password: { label: "Password", type: "password" }
},
async authorize(credentials){
try{
const response = await fetch(`http://localhost:5001/auth/login`,{
method: "POST",
body: JSON.stringify(credentials),
headers: {'Content-type': 'application/json'}
})
const token = (await response).json()
if (response.ok && token) {
return token
}
} catch (error) {
console.log(error)
}
return null
}
})
],
})
and I have the following page:
import { getProviders, signIn } from "next-auth/react"
export default function Singin({ providers:{credentials} }) {
return (
<form method="post" action={credentials.callbackUrl}>
<label>
Email address
<input type="email" id="email" name="email" />
</label>
<label>
Password
<input type="password" id="password" name="password" />
</label>
<button type="submit">Sign in with Email</button>
</form>
)
}
export async function getServerSideProps(context) {
const providers = await getProviders()
return {
props: { providers },
}
}
I used credentials.callbackUrl in order to send the form data to the credentials but doesn't work and next-auth redirects to that page instead of make the auth.
How can I set this page?
Thanks

Try to call the signIn method and pass the credentials to it:
import { signIn } from 'next-auth/react';
export default function Singin() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
await signIn('creadentials', {
email,
password,
});
};
return (
<form method='post' onSubmit={handleSubmit}>
<label>
Email address
<input
type='email'
id='email'
name='email'
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</label>
<label>
Password
<input
type='password'
id='password'
name='password'
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</label>
<button type='submit'>Sign in with Email</button>
</form>
);
}

Related

API Calls with Axios fail on React

On handleSubmit i am trying to log in using an API hosted on Heroku and made based on ExpressJS. It is working fine when i am using Postman to reach the API on the login endpoint. But when using axios on react it fails.
Heroku login endpoint : https://nodejs-mongodb-authapp.herokuapp.com/login
Code :
import React, { useState } from "react";
import './Login.css' ;
import {FaMountain} from 'react-icons/fa';
import { Form, Button } from "react-bootstrap";
import axios from "axios";
import Cookies from "universal-cookie";
const cookies = new Cookies();
export const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [login, setLogin] = useState(false);
const [state , setState] = useState(false);
const axios = require("axios");
const handleSubmit = (event) =>{
const data = JSON.stringify({
email: "au#outlook.com",
password: "zzz",
});
const config = {
method: "post",
url: "https://nodejs-mongodb-authapp.herokuapp.com/login",
headers: {
"Content-Type": "application/json",
},
data: data,
};
axios(config)
.then((result) => {
alert("in thenn");
// setLogin(true);
// cookies.set("TOKEN", result.data.token, {
// path: "/",
// });
// navigate('/auth');
})
.catch((error) => {
error = new Error();
});
}
return(
<div className="p1">
<div className="log">
<form className="formFields" >
<div className="lfa">
<FaMountain />
</div>
<p>LOG IN</p>
<Form onSubmit={(e)=>handleSubmit(e)} className="form_">
{/* email */}
<Form.Group controlId="formBasicEmail">
<Form.Control
type="email"
name="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter email"
/>
</Form.Group>
{/* password */}
<Form.Group controlId="formBasicPassword">
<Form.Control
type="password"
name="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
</Form.Group>
{/* submit button */}
<Button
variant="primary"
type="submit"
onClick={(e) => handleSubmit(e)}
>
Login
</Button>
</Form>
</form>
</div>
{/* {login ? (
<p className="text-success">You Are Logged in Successfully</p>
) : (
<p className="text-danger">You Are Not Logged in</p>
)} */}
</div>
)
}
The API is public for the moment you can try login with those credentials on PostMan :
Well, I managed to test it and it does respond. The request should be done like this:
import React, { useState } from "react";
import { FaMountain } from "react-icons/fa";
import { Form, Button } from "react-bootstrap";
import Cookies from "universal-cookie";
const cookies = new Cookies();
export const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [login, setLogin] = useState(false);
const axios = require("axios");
const handleSubmit = (event) => {
event.preventDefault();
const data = JSON.stringify({
email: "au#outlook.com",
password: "zzz"
});
const config = {
method: "post",
url: "https://nodejs-mongodb-authapp.herokuapp.com/login",
headers: {
"Content-Type": "application/json"
},
data: data
};
axios(config)
.then((result) => {
alert("in thenn");
console.log(result);
setLogin(true);
cookies.set("TOKEN", result.data.token, {
path: "/"
});
})
.catch((error) => {
error = new Error();
});
};
return (
<div className="p1">
<div className="log">
<div className="lfa">
<FaMountain />
</div>
<p>LOG IN (Login State {login.toString()})</p>
<p>Token: {cookies.get('TOKEN')}</p>
<Form onSubmit={(e) => handleSubmit(e)} className="form_">
{/* email */}
<Form.Group controlId="formBasicEmail">
<Form.Control
type="email"
name="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter email"
/>
</Form.Group>
{/* password */}
<Form.Group controlId="formBasicPassword">
<Form.Control
type="password"
name="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
</Form.Group>
{/* submit button */}
<Button
variant="primary"
type="submit"
onClick={(e) => handleSubmit(e)}
>
Login
</Button>
</Form>
</div>
{/* {login ? (
<p className="text-success">You Are Logged in Successfully</p>
) : (
<p className="text-danger">You Are Not Logged in</p>
)} */}
</div>
);
};
Since you are sending a JSON with the access information through the body, you have to take the JSON structure and then chain it to send it through post, and you have to add the ContentType: application/json header.
UP: When forms are used and you use an input type submit, every time the login button is clicked, the component is updated, to avoid this add the following inside the function event.preventDefault();
Test it here

i want to show details on same page

i am developing an application i.e supply chain management application on reactJS, NodeJS and blockchain.
Frontend code:
import React, { Component } from 'react'
import { useState, useEffect } from "react";
import axios from "axios";
import { useNavigate } from 'react-router-dom';
const SignUp = () => {
const navigate = useNavigate();
const flag=0;
const [data, setData] = useState({
uname: "",
email: "",
location: "",
budget: "",
password: ""
});
const handleChange = (e) => {
const value = e.target.value;
setData({
...data,
[e.target.name]: value
});
};
const handleSubmit = (e) => {
e.preventDefault();
const userData = {
uname: data.uname,
email: data.email,
location: data.location,
budget: data.budget,
password: data.password
};
axios
.post("http://localhost:8080/api/signup/", userData)
.then((response) => {
console.log(response);
})
.catch((error) => {
if (error.response) {
console.log(error.response);
console.log("server responded");
} else if (error.request) {
console.log("network error");
} else {
console.log(error);
}
});
navigate(`/home`)
};
return (
<form>
<h3>Sign Up</h3>
<div className="mb-3">
<label>User Name</label>
<input
type="text"
name="uname"
value={data.uname}
className="form-control"
placeholder="User name"
onChange={handleChange}
/>
</div>
<div className="mb-3">
<label>Email address</label>
<input
type="email"
name="email"
value={data.email}
className="form-control"
placeholder="Enter email"
onChange={handleChange}
/>
</div>
<div className="mb-3">
<label>Location</label>
<input
type="text"
name="location"
value={data.location}
className="form-control"
placeholder="Location"
onChange={handleChange}
/>
</div>
<div className="mb-3">
<label>Budget</label>
<input
type="Number"
name="budget"
value={data.budget}
className="form-control"
placeholder="Budget"
onChange={handleChange}
/>
</div>
<div className="mb-3">
<label>Password</label>
<input
type="password"
name="password"
value={data.password}
className="form-control"
placeholder="Enter password"
onChange={handleChange}
/>
</div>
<div className="d-grid">
<button type="submit" onClick={handleSubmit}className="btn btn-primary">
Sign Up
</button>
</div>
<p className="forgot-password text-right">
Already registered sign in?
</p>
</form>
);
};
export default SignUp;
here if user successfully registered then i want to show deatils of the user on the same page. how should i do that?
i have attached the code and the screenshot of the page.
currently i am on my account page.
Inside of your handle submit
You can just navigate after the axios.then callback
Or if you want the behavior to be that user submits -> register success -> show success -> then redirect, you can setTimeout for say 1000ms and then navigate.
axios
.post("http://localhost:8080/api/signup/", userData)
.then((response) => {
console.log(response);
})
.then(() => {
setTimeout(() => navigate(`/home`), 1000);
}
.catch((error) => {
if (error.response) {
console.log(error.response);
console.log("server responded");
} else if (error.request) {
console.log("network error");
} else {
console.log(error);
}
});
If you mean, show the user data after a successful registration and assuming you're calling an api to register the user and you're getting the user details back on success, you can handle that in your handleSubmit method.
Here's an example
const showUserDetails = (userDetails) => {
// Code that shows user details
// Probably using state
};
const handleSubmit = (e) => {
e.preventDefault();
const userData = {
...
axios
.post("http://localhost:8080/api/signup/", userData)
.then((response) => {
// handle here
showUserDetails(response);
})
.catch((error) => {
if (error.response) {
...
} else {
console.log(error);
}
});
};

next-auth custom signIn form don't pass username and password to [...nextauth].js

I wanna use custom signin page for next-auth
problem is that I can not pass data from signin page to [...nextauth].js .
signIn('credentials', { redirect: false, phone: phone, password: password })
can access to provider in [..nextauth].js , but
Providers.Credentials({... didn't run for getting token from API .
1.[...nextauth].js
import NextAuth from 'next-auth'
import Providers from 'next-auth/providers'
import axios from 'axios'
import { useRouter } from 'next/router'
const providers = [
Providers.Credentials({
id: 'credentials',
name: 'credentials',
authorize: async (credentials) => {
const user = await axios.post('MyAPI',
{
phone: credentials.phone,
password: credentials.password
},
)
}
})
]
const callbacks = {
// Getting the JWT token from API response
async session(session, user) {
session.accessToken = user.token
return session
}
}
const options = {
providers,
callbacks
}
export default (req, res) => NextAuth(req, res, options)
2.signin.js
import { useState } from "react";
import { signIn, csrfToken } from 'next-auth/client';
export default function Login() {
const [phone, setPhone] = useState("");
const [password, setPassword] = useState("");
const handleSubmit = async (e) => {
// e.preventDefault();
await signIn('credentials', { redirect: false, phone: phone, password: password })
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>Phone</label>
<input
id="username"
name="username"
type="text"
placeholder="Phone"
onChange={(e) => setPhone(e.target.value)}
value={phone}
/>
</div>
<div>
<label>Password</label>
<input
id="password"
name="password"
type="password"
placeholder="Password"
onChange={(e) => setPassword(e.target.value)}
value={password}
/>
</div>
<button type="submit">
Login
</button>
</form>
);
}
in your [...nextauth].js, you need to specify the credentials:
...
credentials: {
username: { label: "Username", type: "text" },
password: { label: "Password", type: "password" }
}
...
Follow the docs https://next-auth.js.org/providers/credentials
A suggestion:
if your backend is self-hosted, why not to query your db directly as [...nextauth].js runs on the backend?

I can't find an example of how to make an HTTP POST request using useEffect hook along with axios

Lately, I've been trying to make an HTTP POST request using the useEFfect hook along with axios, but the code returns this error in the console: Error: Request failed with status code 422. The POST request is always successfully made when I make it from the form onSubmit handler. However, when I try to make it from the useEffect hook, it gives that error. Can anybody help me with what I'm doing wrong? Here's the code:
import React, { useState, useEffect } from "react";
import axios from "axios";
function RandomPost() {
const [input, setInput] = useState({
name: "",
email: "",
companyName: "",
password: "",
});
const handleChange = (event) => {
setInput({ ...input, [event.target.id]: event.target.value });
};
const handleSubmit = (e) => {
e.preventDefault();
};
useEffect(() => {
const { name, email, companyName, password } = input;
axios
.post(`https://01hire.collaq.com/user/createCompany`, input)
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
}, [input]);
const { name, email, companyName, password } = input;
return (
<div>
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" id="name" value={name} onChange={handleChange} />
</label>
<label>
Email:
<input type="text" id="email" value={email} onChange={handleChange} />
</label>
<label>
Company Name:
<input
type="text"
id="companyName"
value={companyName}
onChange={handleChange}
/>
</label>
<label>
Password:
<input
type="password"
id="password"
value={password}
onChange={handleChange}
/>
</label>
<button type="submit">Submit</button>
</form>
</div>
);
}
export default RandomPost;

Sign-Up issue with AWS-Amplify

I did the configuration for aws-amplify in my react application for the following required properties.
mandatorySignIn, region, uerPoolId, userPoolWebClientId
import Amplify from "aws-amplify";
import config from "./config";
Amplify.configure({
Auth: {
mandatorySignIn: true,
region: config.cognito.REGION,
uerPoolId: config.cognito.USER_POOL_ID,
userPoolWebClientId: config.cognito.APP_CLIENT_ID
}
});
Sign-Up has been done using an async function as in the following react component.
import React, { useState } from "react";
import { Auth } from "aws-amplify";
function Registration() {
const [firstName, setFirstName] = useState("");
const [lastName, setLasttName] = useState("");
const [email, setEmail] = useState("");
const [username, setusername] = useState("");
const [password, setPassword] = useState("");
const currentConfig = Auth.configure();
console.log("current", currentConfig);
const handleRegister = async event => {
event.preventDefault();
console.log(firstName, lastName, username, password);
try {
const signUpResponse = await Auth.signUp({
username,
password,
attributes: {
email
}
});
console.log(signUpResponse);
} catch (err) {
console.log("ERROR", err);
}
};
return (
<React.Fragment>
<form onSubmit={handleRegister}>
<label>
First Name
<input
type="text"
id="firstname"
onChange={({ target: { value } }) => setFirstName(value)}
/>
</label>
<br />
<label>
Last Name
<input
type="text"
id="lastname"
onChange={({ target: { value } }) => setLasttName(value)}
/>
</label>
<br />
<label>
Email
<input
type="email"
id="email"
onChange={({ target: { value } }) => setEmail(value)}
/>
</label>
<br />
<label>
User Name
<input
type="text"
id="username"
onChange={({ target: { value } }) => setusername(value)}
/>
</label>
<br />
<label>
Password
<input
type="password"
id="password"
onChange={({ target: { value } }) => setPassword(value)}
/>
</label>
<br />
<input type="submit" value="Submit" />
</form>
</React.Fragment>
);
}
export default Registration;
But when I tried to sign Up, I get the following error in console.
But when I check for the Auth configuration by Auth.configure(), I can see the configuration object with the properties, I have given.
What are the additional required properties of aws-amplify congfiguration that I need to add ?
You need to import awsconfig from '../aws-exports' to Amplify.configure:
Amplify.configure({
...awsconfig,
Auth: {
mandatorySignIn: true,
region: config.cognito.REGION,
uerPoolId: config.cognito.USER_POOL_ID,
userPoolWebClientId: config.cognito.APP_CLIENT_ID
}
})
This file will appear after run amplify init in root directory.
More info: Amplify Getting Started
As #Alexander answered, you should pass awsconfig to Amplify.configure.as a result, you can remove the unnecessary assigned parameters.
import awsconfig from './aws-exports';
Amplify.configure({
...awsconfig,
Auth: {
mandatorySignIn: true,
}
})

Resources