I just started learning React and I'm currently working on setting up my login system to connect with my API. I am attempting to make a call from my React Redux app to my .NET Core (3.1) API. The React app is located at http://localhost:3000, while the API is at https://localhost:44383/ (not sure if this detail matters).
When making a POST request, I'm encountering a CORS error as shown below:
https://i.sstatic.net/NGboF.png
I don't believe the issue originates from the API because I have configured the cross-origin requests policy in my startup.cs ConfigureServices method (C#)
services.AddCors(options =>
{
options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
options.AddPolicy(name: "react",
builder =>
{
builder.WithOrigins("http://localhost:3000/").WithHeaders(HeaderNames.AccessControlAllowOrigin, "http://localhost:3000"); ;
});
});
and applied that policy within the configure method
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("react");
app.UseAuthentication();
app.UseAuthorization();
app.UseAuth();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Upon inspection using Postman, it is evident that the correct header is being attached: https://i.sstatic.net/q5oYs.png
While I'm not as experienced with React, here are the relevant parts of my authentication process including the API call with headers:
loginEffect() function of AuthSaga.ts (React/Typescript)
export function* loginEffect(action: any) {
console.log("loginEffect", action)
try {
const data = {
headers: {
"content-type": "application/json",
"Access-Control-Allow-Origin": "http://localhost:3000/"
},
body: {
...action.payload,
},
}
const { timeoutDelay, response } = yield race({
timeoutDelay: delay(10000),
response: call(AuthAPI.postLogin, data),
})
if (timeoutDelay) {
yield put(setAuthFailure("Server timed out"))
}
if (response) {
if (response.status === 200) {
console.log("200");
const responseJson = yield response.json()
yield put(loginSuccess(responseJson))
} else {
console.log("fail");
const responseJson = yield response.json()
yield put(setAuthFailure(responseJson))
}
}
} catch (error) {
yield put(setAuthFailure("Something went wrong. Try again later."))
}
}
login.tsx
export const Login: React.FC = (props) => {
const [username, setUsername] = useState("")
const [password, setPassword] = useState("")
const dispatch = useDispatch()
const handleSubmit = () => {
dispatch(login({ UserName: username, Password: password }))
}
return (
<PageWrapper>
<LoginWrapper>
<input
placeholder="Username"
onChange={(e) => setUsername(e.target.value)}
></input>
<input
placeholder="Password"
onChange={(e) => setPassword(e.target.value)}
></input>
</LoginWrapper>
<button onClick={handleSubmit}>Submit</button>
</PageWrapper>
)
}
and AuthAPI.ts
export const AuthAPI: AuthAPIInterface = {
async postLogin(data: any): Promise<object> {
const postLoginUrl: string = `${ baseApi.authUrl }/login`
console.log('[URL FOR postLogin]', postLoginUrl);
console.log(data);
return fetch(postLoginUrl, {
method: 'POST',
headers: data.headers,
credentials: 'include',
body: JSON.stringify(data.body)
})
},
async postRegister(data: any): Promise<object> {
const postRegisterUrl: string = `${ baseApi.authUrl }/register`
console.log('[URL FOR postRegister]', postRegisterUrl);
return fetch(postRegisterUrl, {
method: 'POST',
headers: data.headers,
credentials: 'include',
body: JSON.stringify(data.body)
})
}