Trying to get session from http response in Angular 2 - http

I have an Angular 2 app which runs on port 8000 on the lite server. My express app (back-end) runs on port 3000.
When I send my credentials to the back-end which runs on port 3000, then I can see that I had succesfully logged in on port 8000. But I don't get a session as a response from the back-end. Here is a screenshot of it link:
As you can see the response says Session not found.
And when I succesfully log in on port 3000. Then I do get a session as response from the back-end. Here is a screenshot of it link:
Also here is a screenshot of logging in on port 3000 through Postman (Rest client) link:
And here is a screenshot of getting a session as a response on port 3000 link:
So now I can conclude that there is no problem at the back-end.
My question is: how can I also get the session as a response on port 8000?
Here is my code:
app.component.ts:
export class AppComponent {
//On page refresh the constructor gets called
constructor(private _userService: UserService) {
this._userService.getSession()
.subscribe(
res => {
console.log("app session ");
//log the response which shows a session
console.log(res);
},
error => {
console.log("app session error");
console.log(error);
}
);
}
}
login.component.ts:
export class LoginComponent {
user: User = new User();
loginRes: String;
private toasterService: ToasterService;
public toasterconfig: ToasterConfig = new ToasterConfig({
showCloseButton: true,
tapToDismiss: false,
timeout: 0
});
constructor(private _userService: UserService, toasterService: ToasterService, private router: Router) {
this.toasterService = toasterService;
}
data = {};
onSubmit() {
this._userService.login(this.user)
.subscribe(
//we are using an arrow function here
res => {
this.toasterService.pop('success', 'Success', 'You have logged in ' + res.username);
// I don't use navigate(), because I want a redirect where the page gets refreshed
// this.router.navigate(['/']);
var host = location.host;
console.log("host");
console.log(host);
//redirects where the page also gets refreshed
window.location.href = "http://"+ host;
},
error => {
this.toasterService.pop('error', 'Failed', error._body);
}
);
}
}
user.service.ts:
#Injectable()
export class UserService {
private url: string;
constructor(private _http: Http) {
}
login(user: User) {
this.url = config.getEnvironmentVariable('endPoint')+'api/auth/login';
let data = { "username": user.username, "password": user.password };
let body = JSON.stringify(data);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
console.log("login url " + this.url);
return this._http.post(this.url, body, options)
.map(this.extractData)
.catch(this.handleError);
}
getSession() {
this.url = config.getEnvironmentVariable('endPoint')+'api/auth/';
console.log("session url " + this.url);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
options.body = '';
return this._http.get(this.url, options)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body || {};
}
private handleError(error: any) {
//the Observable catches and throws an error
return Observable.throw(error.message || error);
}
}

Related

Axios getStore is undefined in NextJs api calls. (Redux, NextJs, Jwt)

I am trying to set up authentication for a project. Once a user signs up for our app they get sent to our home page with an id in the query. This id then gets used to submit user and then the jwt token gets saved inside redux state.
All our calls now go through an axios client where the jwt token is passed on every request. The token gets read with store.getState(injectStore)
This all works fine inside getserversideProps, but the issue comes in when using calls on the frontend that goes through NextJs built in 'pages/api' folder. Any calls inside those folders causes the store.getState() to be undefined. I do not understand why since it uses the exact same client as geserversideProps.
Example GetServersideProps(working)
try {
const response = await serverApiClient.get('v1/config');
return {
props: {
},
};
} catch ({ error: { statusCode = 500, message = 'Internal Server Error' } }) {
if (statusCode === 401) {
return {
redirect: {
permanent: false,
destination: '/',
},
};
}
throw new Error(message as string);
}
};
Example Frontend bff call(not working)
try {
// Call below get sent to next built in api
const players = await apiClient.get(`/defenders?sortBy=${statId}&team_id=${teamShortName}`);
return players;
} catch (error) {
return { error };
}
};
export default async function handler(req: NextApiRequest) {
console.log('Start request')
try {
const { sortBy, team_id: teamId } = req.query;
const response = await serverApiClient.get(`/v1/players/picks?position=DEF&sort_by=${sortBy}&team_id=${teamId}`);
Api Client
mergeConfigs(
params: Record<string, string>,
headers: Record<string, string>,
configs: Record<string, string>,
): AxiosRequestConfig {
const defaultConfigs = ApiClient.getDefaultConfigs();
*const token = store?.getState()?.jwtToken?.value*
//ISSUE ABOVE - This store .getState() is only undefined in nextJS api folder calls.
return {
...defaultConfigs,
...configs,
params,
headers: {
...defaultConfigs.headers,
...headers,
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
};
}
get(
uri: string,
params = {},
headers = {},
configs = {},
): Promise<AxiosResponse | any> {
return this.client
.get(uri, this.mergeConfigs(params, headers, configs))
.then((response) => {
return (response.data ? response.data : response);
})
.catch((error) => {
const errorObject = {
error: error?.response?.data,
};
throw Object.assign(errorObject);
});
}
If anyone has some advice on why that getStore is undefined in frontend-to-backend calls please assist. Thanks all!

How to get logged user in vuejs

I made a jwt authetication using asp.net core and vuejs
this is my auth controller :
[Route("Login")]
[HttpPost]
public IActionResult Login(LoginArgument loginArgument)
{
var user = _userService.GetByEmail(loginArgument.Email);
if (user == null) return BadRequest(error: new { message = "Invalid credential : verify email" });
if (!BC.BCrypt.Verify(text: loginArgument.Password, hash: user.Password))
{
return BadRequest(error: new { message = "Invalid credential : verify password" });
}
var jwt= _jwtService.Generate(user.Id);
Response.Cookies.Append(key: "jwt", value: jwt, new Microsoft.AspNetCore.Http.CookieOptions
{
HttpOnly=false,
SameSite=Microsoft.AspNetCore.Http.SameSiteMode.None
}) ;
return Ok(user);
}
[Route("User")]
[HttpGet]
public IActionResult User()
{
try
{
var jwt = Request.Cookies["jwt"];
var token = _jwtService.Verify(jwt);
int userId = int.Parse(token.Issuer);
var user = _userService.GetById(userId);
return Ok(user);
}
catch (Exception)
{
return Unauthorized();
}
}
and this is the login in vue
<script lang="ts">
import { reactive } from 'vue';
import { useRouter } from "vue-router";
export default {
name: "Login",
setup() {
const data = reactive({
email: '',
password: ''
});
const router = useRouter();
const submit = async () => {
await fetch('https://localhost:44391/api/Auth/Login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(data)
});
await router.push('/Countries');
}
return {
data,
submit
}
},
}
the login part is working in front and back sides perfectly and i can see the cookies
the problem is when i try to get the logged user. in back side i can get it successfully but in front it says that no user is logged
here is the loggedUser vue
<script lang="ts">
import { onMounted, ref } from 'vue';
export default {
name: "LoggedUser",
setup() {
const message = ref('You are not logged in!');
onMounted(async () => {
const response = await fetch('https://localhost:44391/api/Auth/User', {
headers: { 'Content-Type': 'application/json' },
credentials: 'include'
});
const content = await response.json();
message.value = `hi ${content.name}`;
});
return {
message
}
}
}
Here is the errors i got when i inspect the page :
this issues appear the moment of login
1- Mark cross-site cookies as Secure to allow setting them in cross-site contexts
2- Migrate entirely to HTTPS to have cookies sent to same-site subresources
this one appears when i call loggedUser in front even so it works in the back side
{type: "https://tools.ietf.org/html/rfc7235#section-3.1", title: "Unauthorized", status:
401,…}
status: 401
title: "Unauthorized"
traceId: "00-b4a9f6fee8dff6439952ded0bb50005d-43c9aee84c454b40-00"
type: "https://tools.ietf.org/html/rfc7235#section-3.1"
You need to send the access token in the request headers
Example:
let token = '???'
const response = await post('localhost/api/auth/user', {
headers: {
'Content-Type': 'application/json'
'Authorization' : 'Bearer '+ token
}
});

Angular2 response not mapping to TypeScript object

I'm struggling to figure out why the response I get from my API isn't mapping to an object that I have in typescript.
Here's the function in my service that calls the API:
register(user: IUser): Observable<IUser> {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
var options = new RequestOptions({
headers: headers,
url: this._registerUrl,
body: JSON.stringify(user)
});
return this._http.post(this._registerUrl, { user }, options)
.map((res: Response) => res.json() as IUser)
.catch(this.handleError);
}
This is the function that calls the service:
register(): void {
let user: IUser = {
email: this.email,
username: this.username,
password: this.password
}
this._userService.register(user)
.subscribe(result => {
debugger;
if(result.errorCode > 0)
this.handleError(result.errorCode);
else {
localStorage.setItem('userId', result.userId.toString());
localStorage.setItem('username', result.username.toString());
localStorage.setItem('email', result.email.toString());
}
});
}
The object that I am returning from the API matches the object that I have in the frontend. It is returning the data and I can see it in the body of my response. All of the data is right, but it's in the body and is not turning it into an IUser object.
Does anybody have any ideas? Thanks.
EDIT
This is what the response object looks like when it comes back from the service.

Angular 2 http Post failing on client side but data is getting inserted in the Database

Service
The HTTP post service
addUser(body: Object): Observable<any> {
let bodyString = JSON.stringify(body);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(this.baseUrl + 'api/v3/user/Adduser', body, options)
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}
Component
When I call this method, the data is getting inserted into the database, but I am unable to get the response. It is going into the error block. Please look at the image below for error information.
addUser(items: any) {
this.signupService.addUser(items)
.subscribe(response => {
this.eventsEmitter.broadcast('Success', 'Changes Saved Succesfully');
this.router.navigate(['/login']);
},
error => {
debugger;
this.eventsEmitter.broadcast('Error', 'Error Occured');
});
}
Error Information
Not sure how to resolve this. Can you please tell me the changes to make it work?
Web API Controller
This is the web API controller
[HttpPost]
[Route("AddUser")]
public async Task<IHttpActionResult> AddUser([FromBody]UsersModel model)
{
try
{
await _userService.AddUser(model);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Created);
return ResponseMessage(response);
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}
Try to do the following changes :
addUser(items: any) {
this.signupService.addUser(items)
.subscribe(response => {
this.eventsEmitter.broadcast('Success', 'Changes Saved Succesfully');
this.router.navigate(['/login']);
});
}
Web API Controller :
[HttpPost]
[Route("AddUser")]
public async Task<IHttpActionResult> AddUser([FromBody]UsersModel model)
{
try
{
await _userService.AddUser(model);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
return ResponseMessage(response);
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}
Http Service :
addUser(body: Object): Observable<any> {
let bodyString = JSON.stringify(body);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(this.baseUrl + 'api/v3/user/Adduser', body, options)
.map((response : Response) => {
if (response.status < 200 || response.status >= 300) {
throw new Error('This request has failed ' + response.status);
}
else {
return response.json();
}
});
}
Make sure you import the necessary dependencies:
import { Observable } from "rxjs/Observable";
import 'rxjs/add/observable/throw';

Angular2 Call login function from service in component and return error

I'm trying to call a service HTTP method and eventually return an error message but after a week of trying many things (Promises, Observables, ...) I can't get it to work. I hope anybody can help me out?
I'm kind of new to Angular2 and working alone on this project, with no one else around me with any Angular expertise. I did get a 3-day training course.
Component
#Component({
templateUrl: 'build/pages/login/login.html'
})
export class LoginPage {
error: string;
constructor(private navController: NavController, private auth: AuthService) {
}
private login(credentials) {
// Method calling the login service
// Could return an error, or nothing
this.error = this.auth.login(credentials);
// If there is no error and the user is set, go to other page
// This check is executed before previous login methode is finished...
if (!this.error && this.auth.user) {
this.navController.setRoot(OverviewPage);
}
}
}
AuthService
#Injectable()
export class AuthService {
private LOGIN_URL: string = "http://localhost:8080/rest/auth";
private USER_URL: string = "http://localhost:8080/rest/user";
private contentHeader: Headers = new Headers({
"Content-Type": "application/json"
});
errorMessage: string;
user: User;
constructor(private http: Http) {
}
login(credentials) {
let contentHeader = new Headers({
"Content-Type": "application/json"
});
this.http.post(this.LOGIN_URL, JSON.stringify(credentials), { headers: contentHeader })
.map(res => res.json())
.catch(this.handleError)
.subscribe(
data => this.handleLogin(data),
err => this.handleError
);
// could return an errorMessage or nothing/null
return this.errorMessage;
}
private handleLogin(data) {
let token = data.token;
this.getAccount(token);
}
private getAccount(token) {
let authHeader = new Headers({
"Content-Type": "application/json",
"X-Auth-Token": token
});
this.http.get(this.USER_URL, { headers: authHeader })
.map(res => res.json())
.catch(this.handleError)
.subscribe(
data => this.setUser(data),
err => this.errorMessage = err
);
}
private setUser(data) {
this.user = new User(data.naam, data.voornaam);
}
private handleError(error) {
// this.errorMessage is not saved?
if (error.status === 401) {
this.errorMessage = '401';
} else if (error.status === 404) {
this.errorMessage = '404';
} else {
this.errorMessage = 'Server error';
}
return Observable.throw(error.json() || 'Server error');
}
}
I think your problem is that your login method is returning a flat value (errorMessage). Since the login method is making an asynchronous request that value will not be initialized, it will always return null. If I were to set this up I would have the login method return an Observable.
Then to make things a bit more complicated it appears you want to make a consecutive call after login to get the logged in user. If you don't want your login method to emit until you've completed both calls you have to combine them somehow. I think switch can do this.
#Injectable()
export class AuthService {
private LOGIN_URL: string = "http://localhost:8080/rest/auth";
private USER_URL: string = "http://localhost:8080/rest/user";
private contentHeader: Headers = new Headers({
"Content-Type": "application/json"
});
user: User;
constructor(private http: Http) {
}
login(credentials) {
let contentHeader = new Headers({
"Content-Type": "application/json"
});
let response:Observable<Response> = this.http.post(this.LOGIN_URL, JSON.stringify(credentials), { headers: contentHeader });
//Take response and turn it into either a JSON object or
//a string error.
//This is an Observable<any> (any is returned by json())
let jsonResponse = response.map(res => res.json())
.catch(err => this.handleError(err));
//Take JSON object and turn it into an Observable of whatever the
//login request returns
//This is an Observable<Observable<any>> (Observable<any> is returned
//by handleLogin
let userResponse = jsonResponse.map(
data => this.handleLogin(data)
);
//Switch to the observable of the login request
//This is an Observable<any>, we will switch to the Observable<any>
//returned by handleLogin
let finalResponse = userResponse.switch();
//Hide actual response value from user. This will return an
//observable that will emit null on success and an error message
//on error
//Again, an Observable<any> since we're mapping to null
return finalResponse.map(res => null);
}
//We need to return this call as an observable so we can wire it into
//our chain
private handleLogin(data) {
let token = data.token;
return this.getAccount(token);
}
private getAccount(token) {
let authHeader = new Headers({
"Content-Type": "application/json",
"X-Auth-Token": token
});
let loginResponse = this.http.get(this.USER_URL, { headers: authHeader })
.map(res => res.json())
.catch((err) => this.handleError(err));
loginResponse.subscribe(
data => this.setUser(data)
);
return loginResponse;
}
private setUser(data) {
this.user = new User(data.naam, data.voornaam);
}
private handleError(error) {
let errorMessage = "Uninitialized";
if (error.status === 401) {
errorMessage = '401';
} else if (error.status === 404) {
errorMessage = '404';
} else {
errorMessage = error.json() || 'Server error';
}
return Observable.throw(errorMessage);
}
}
Now in your login component you will need to listen asynchronously to the response. This won't happen immediately (probably pretty quick with localhost, but may take a while in the real world) so I've added a loginDisabled that you can use to prevent the user from hitting the login button twice while waiting for the login request to be fulfilled.
#Component({
templateUrl: 'build/pages/login/login.html'
})
export class LoginPage {
error: string;
loginDisabled:boolean = false;
constructor(private navController: NavController, private auth: AuthService) {
}
private login(credentials) {
// Method calling the login service
// Could return an error, or nothing
this.loginDisabled = true;
this.auth.login(credentials).subscribe(
rsp => {
//On success, navigate to overview page
this.navController.setRoot(OverviewPage);
}, err => {
//On failure, display error message
this.error = err;
this.loginDisabled = false;
});
}
}
No promises this is all correct (I don't have anything to test it against) but it should be the right general direction.

Resources