I want to create a react web app containing a login. My backend is implemented with JAX-RS and BASIC authentication. Here is a snippet of the web.xml and a Resource.
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>api</web-resource-name>
<url-pattern>/api/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>ROLE</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>ROLE</role-name>
</security-role>
Resource:
@GET
@PermitAll
@Produces(MediaType.APPLICATION_JSON)
public List<OnlineStackDto> getData() {
return dataService.getData();
}
All Requests from react are bundled in one file, request.js. Here is the get function as an example.
const user = 'username';
const pass = 'password';
export function get(url) {
return fetch(url,
{
method: 'GET',
headers: {
Authorization: "Basic " + btoa(user + ":" + pass)
}
}
);
}
Of course, hardcoding username and password is not how the app can be deployed later. The function is called like this:
import {get} from "./request";
import React from "react";
export default class DataComponent extends React.Component {
componentDidMount() {
get('onlinestacks').then(data => this.setState({myData: data}));
}
}
The login-logic is realized using react-router and React 16.3 Context-API. Thus, I can access the username/password in every component using a Consumer. Here is an example of how the data is set and used. For a more complete example, see this question.
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
user: {
username: '',
password: ''
}
};
this.login = this.login.bind(this);
}
login(username, password) {
this.setState({
user: {
username: username,
password: password
}
});
}
render() {
return (
<UserContext.Provider value={this.state.user}>
<Header/>
/*Other Components*/
</UserContext.Provider>
);
}
}
export default class Header extends React.Component {
render() {
return (<header>
<UserContext.Consumer>{value =>
<div className="username">{value.username}</div>
}
</UserContext.Consumer>
</header>);
}
}
My question is:
How can I use username and password from the Context in my requests without having to pass them everytime I want to make a request?
UserContext. I can access it as shown in theHeadercomponent. I don't know how to use this data in therequest.jsfile. Just setting it as a global variable feels wrong and the only other way I could think of, is to pass the user as a parameter to the request, likefunction get(url, user). But this would make it necessary to implement aUserContext.Consumerin every component which needs to fetch data. This feels unnecessarily complicated.requestmethod? The proposed solution would depend on that. There are many ways to do it and each has its own drawbacks.