the server responded with a status of 403 (Forbidden) angular - java

When I try to call with this.http.get and #GetMapping I am able to send the call to spring controller,
When I try to change from this.http.get to this.http.post and from #GetMapping to #PostMapping I am not able to call the spring controller /api/v1/basicauth method.
As I am having username and password I want to use PostMapping only
My code as below:-
Angular
var formData: any = new FormData();
formData.append("userName", username);
formData.append("password", password);
let params = new HttpParams();
params = params.append('username', username);
params = params.append('password', password);
return this.http.post<any>('/api/v1/basicauth', { formData }).pipe(map((res) => {
this.username = username;
this.password = password;
}));
Spring boot:-
#PostMapping(path = "/basicauth")
public AuthenticationBean helloWorldBean(#RequestBody UserDetails user) {
log.info("Start helloWorldBean method");
UserDetails.java
public class UserDetails {
private int userId;
private String userName;
private String password;
}

Do not use FormData (Angular) as your controller is accepting #RequestBody
your formData should be something like
var formData = {"username": username, "password": password};
Rest will deserilize automatically it to UserDetails class

Client side
login(username: string, password: string) {
return this.http.post<any>('/api/v1/basicauth', { username, password })
.pipe(map(user => {
// eg.
// localStorage.setItem('currentUser', JSON.stringify(user));
return user;
}));
Example from: https://jasonwatmore.com/post/2019/06/22/angular-8-jwt-authentication-example-tutorial
Server side
You are retrieving paramaters with #RequestParam, which means you're expeting parametes as http://host:8080/api/auth?password=abc&....
Please check https://www.baeldung.com/spring-request-response-body

Related

Angular / Spring Boot | error: SyntaxError: "JSON.parse: unexpected character at line 1 column 1 of the JSON data"

I am currently working on a tutorial to get to know Spring Boot and currently facing the following problem.
During my registration process (works correctly -> user ends up in the database) I get the status code 200/OK in the browser console, but also an error message regarding an incorrect syntax:
My backend code looks like this:
AuthController:
#RestController
#RequestMapping(value = "/api/auth")
#AllArgsConstructor
public class AuthController {
private final AuthService authService;
private final RefreshTokenService refreshTokenService;
#PostMapping(value = "/signup")
public ResponseEntity<String> signup(#RequestBody RegisterRequest registerRequest) {
/*
* RegisterRequest: Through this class we are transferring the user details like username, password and email as part of the RequestBody (DTO)
* */
authService.signUp(registerRequest);
return new ResponseEntity<>("Registration Successful", null, OK);
}
....
AuthService:
#Transactional
public void signUp(RegisterRequest registerRequest) {
User user = new User();
user.setUsername(registerRequest.getUsername());
user.setEmail(registerRequest.getEmail());
user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
user.setCreated(now());
user.setEnabled(false);
userRepository.save(user);
String token = generateVerificationToken(user);
String message = mailContentBuilder.build("Thank you for signing up to Spring Reddit, please click on the below url to activate your account : "
+ ACTIVATION_EMAIL + "/" + token);
mailService.sendMail(new NotificationEmail("Please Activate your account", user.get
Email(), message));
}
Used DTO:
public class RegisterRequest {
private String email;
private String username;
private String password;
}
My frontend code looks like:
SignUpComponent:
signUp() {
this.signUpRequestPayload.email = this.signUpForm.get('email').value;
this.signUpRequestPayload.password = this.signUpForm.get('password').value;
this.signUpRequestPayload.username = this.signUpForm.get('username').value;
this.authService.signUp(this.signUpRequestPayload).subscribe((data) => {
console.log('Sign up successful', data);
});
}
AuthService:
#Injectable({
providedIn: 'root'
})
export class AuthService {
private headers = new HttpHeaders({ 'Content-Type': 'application/json' });
constructor(private http: HttpClient) { }
signUp(signUpRequestPayload: SignUpRequestPayload): Observable<SignUpRequestPayload> {
const body = JSON.stringify(signUpRequestPayload);
return this.http.post<SignUpRequestPayload>('http://localhost:8080/api/auth/signup', body, { headers: this.headers });
}
}
Used interface:
export class SignUpRequestPayload {
email: string;
password: string;
username: string;
}
What am I doing wrong here?
I solved it like this:
signUp(signUpRequestPayload: SignUpRequestPayload): Observable<string> {
const body = signUpRequestPayload;
return this.http.post('http://localhost:8080/api/auth/signup', body, { responseType: 'text', headers: this.headers });
}
I had to remove from the post method and set the responseType to 'text'. I also had to remove the JSON.stringify() method and set the return type to Observable.
As your response("Registration Successful") is not valid JSON.
So please remove <SignUpRequestPayload> from below line
return this.http.post<SignUpRequestPayload>

Redirect in Play framework controller not working

I am trying to redirect to another route, and even tho I get the html response, and in the inspect element I see that the page sends a get request to the next route, it does not load. Why ?
My routes:
GET / controllers.HomeController.index
GET /hello controllers.HomeController.hello
GET /home controllers.HomeController.home
GET /login controllers.HomeController.login
GET /register controllers.HomeController.signup
GET /auth/login controllers.AuthController.login(username: String, password: String)
My jquery:
function login () {
var username = $('#username').val();
var password = $('#password').val();
$.get("/auth/login", {username: username, password: password});
}
My controller for the /auth/login route:
#Inject
private AuthService authService;
public Result login(String username, String password) {
// post request
boolean login = authService.login(username, password);
if (login)
return redirect(controllers.routes.HomeController.hello());
else
return redirect(controllers.routes.HomeController.signup());
}
My authService:
public class AuthService extends RestService {
public boolean login(String username, String password) {
WSRequest request = createRequest("/users/login")
.setQueryParameter("username", username)
.setQueryParameter("password", password);
JsonNode jsonNode = get(request);
boolean b = jsonNode.asBoolean();
return b;
}
}
My register and hello methods in HomeController:
public Result hello() { return ok(views.html.hello.render()); }
public Result signup() { return ok(views.html.signup.render()); }
I want that the page loads. I do not know why it does not load in the first place even tho I get the html response on /auth/login route in the inspect element it just does not want to completely redirect it. Really weird.

404 error on post, but my server gets the data fine but does not return properly

I am trying to rewrite my login piece with Spring boot. Currently, my data is being posted fine and the backend is getting it, but my success function is not being fired. My backend is throwing no errors, but I am getting a 404 error on the browser.
Here is my post:
$.ajax({
type: "POST",
url: "login",
data: "&username=" + username.value + "&password=" + password.value
}).done(function(response) {
var resp = JSON.parse(response);
if (resp.loginResult === "false") {
//TODO
} else {
//TODO
}
});
Controller:
#Controller
#Scope("session")
public class LoginController {
#GetMapping("/login")
public String login() {
return "login";
}
#PostMapping("/login")
public String login(HttpServletRequest request) {
HttpSession session = request.getSession();
StringBuilder json = new StringBuilder();
String username = request.getParameter("username");
String password = request.getParameter("password");
if (userExists()) {
session.setAttribute("isLoggedIn", "true");
session.setAttribute("userID", username);
session.setAttribute("userType", "employee");
json.append("{");
json.append("\"loginResult\": \"true\",");
json.append("\"resultMessage\": \"Logged in\"");
json.append("}");
} else {
System.out.println("Username or password does not match.");
json.append("{");
json.append("\"loginResult\": \"false\",");
json.append("\"resultMessage\": \"Bad Login\"");
json.append("}");
}
return json.toString();
}
}
I am trying to just return a JSON string which can be parsed on the front end and do whatever needs to be done based off the resultMessage. Sorry if my code is ugly, I am still new to Spring and welcome any suggestions!
Here is the error in my console on the browser:
POST http://localhost:8080/BedrockWeb/login 404 ()
I am assuming I am not returning my JSON string properly.
If you use Spring, then use the conveniences that it provides. You can create following class:
public class LoginResult {
private boolean loginResult;
private String resultMessage;
public LoginResult() { }
public String getResultMessage() {
return resultMessage;
}
public boolean isLoginResult() {
return loginResult;
}
public void setLoginResult(boolean loginResult) {
this.loginResult = loginResult;
}
public void setResultMessage(String resultMessage) {
this.resultMessage = resultMessage;
}
}
Then you have to change your controller method to:
#PostMapping("/login")
#ResponseBody
public LoginResult login(HttpServletRequest request) {
HttpSession session = request.getSession();
String username = request.getParameter("username");
String password = request.getParameter("password");
LoginResult loginResult = new LoginResult();
if (userExists()) {
session.setAttribute("isLoggedIn", "true");
session.setAttribute("userID", username);
session.setAttribute("userType", "employee");
loginResult.setLoginResult(true);
loginResult.setResultMessage("Logged in");
} else {
System.out.println("Username or password does not match.");
loginResult.setLoginResult(false);
loginResult.setResultMessage("Bad Login");
}
return loginResult;
}
The #ResponseBody annotation tells a controller that the object returned is automatically serialized into JSON and passed back into the HttpResponse object. source
Yes, this is because you are not sending JSON response properly.
What you can do is create an object and set the values in that and then try to convert in JSON using
new JSONSerializer().transform(new DateTransformer("MM/dd/yyyy HH:mm:ss"), java.util.Date.class).exclude("*.class").serialize(object);
and send the response to AJAX like below:
return new ResponseEntity<String>(new JSONSerializer().transform(new DateTransformer("MM/dd/yyyy HH:mm:ss"), java.util.Date.class).exclude("*.class").serialize(object), HttpStatus.OK);
NOTE: If you want to do the same with Spring boot then the #ResponseBody annotation is enough. It will convert the object to JSON.

Post Json Object from AngularJs to java JAX-RS service

I google this matter for hours but I still cannot find solution.
Here is my java code
#POST
public String doLogin(User user) {
System.out.println(" = " + user.getUsername());
return "";
}
and
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class User {
String username;
String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
and here is my AngularJs code
angular.module('notesApp', []).controller('MainCtrl', ['$http', function($http) {
var self = this;
self.submit = function() {
$http({
method: 'POST',
url: 'http://127.0.0.1:8080/Test/app/login',
headers : {'Content-Type': 'application/json'},
data: self.user //forms user object
})
.then(function(response) {
console.log(response.data);
return response.data;
}, function(response) {
});
}
}]);
My error message was:
SEVERE: A message body reader for Java class entity.User, and Java type class entity.User, and MIME media type application/json; charset=UTF-8 was not found, as I could not access 'user' Object in java code.
Could you please figure out which part I do wrong? Thank you so much.
You need to read from POST body and not Query Params.
You can use this:
#POST
public String doLogin( User user) {
System.out.println(" = " + user.getUsername());
return "";
}
#QueryParam is used to the queryparams which you'll pass as ?user=xyz#gmail.com
Remove query param You will get a serialized string. deSerialize it to User.
#POST
public String doLogin(User user) {
System.out.println(" = " + user.getUsername());
return "";
}
You are setting the data field on your POST. This sets the HTTP Body, not an HTTP query param.
Check the browser debugger networking panel to ensure that you are sending what you expect to the server. will open it and then 'send' your user and look at what is sent. Does this object look exactly like what User in java expects?

Trying to use Feign to log into Spring OAuth2 server

I'm looking to make a grant_type = password login from a service with Feign to the Spring OAuth2 server. I've confirmed the OAuth2 server works when I make a normal REST call. But when trying with Feign, it fails.
In my service I have:
#Component
#Scope("prototype")
#FeignClient(url = "http://localhost:9999/uaa")
public interface AuthClient {
#RequestMapping(value="/oauth/token", method=RequestMethod.POST)
#Headers({"Authorization: Basic some_base64encoded_client_secret_here=="})
public LoginResponse login(
#Param("username") String username, #Param("password") String password, #Param("grant_type") String grantType);
}
I get this error:
java.lang.ClassCastException: Cannot cast com.sun.proxy.$Proxy129 to org.springframework.web.bind.annotation.RequestMapping
Most examples I find show how to intercept Feign to use OAuth headers/etc. and assume the access token already exists. But this is not my issue. I don't have an access token yet because I'm trying to get the access token from logging in. Any ideas on how I can log in using Feign?
You can map your own response like this:
#Component
#FeignClient(name = "authClient", url = "http://localhost:8080")
public interface AuthClient {
#RequestMapping(value="/oauth/token", method= RequestMethod.POST)
AuthResponse login(#RequestParam("grant_type") String grantType, #RequestParam("username") String username,
#RequestParam("password") String password, #RequestParam("scope") String scope);
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
class AuthResponse {
String access_token;
String token_type;
String refresh_token;
String expires_in;
}
}
public class AuthService {
private final AuthClient authClient;
public AuthService(AuthClient authClient) {
this.authClient = authClient;
}
public AuthClient.AuthResponse authenticate(String login, String password, String scopes) {
return this.authClient.login("password", "admin", "admin", "read+write");
}
}
You can register a request interceptor to add Authorization headers at every request:
#Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("clientId", "clientSecret");
}
This code works with a sample Spring Security OAuth2 server.

Categories

Resources