Basic Auth Send API_KEY to php api - REACTJS - php

I am sending the username and password to the PHP api with the API_KEY in the .env file. How do I get the user name before the semicolon as the password after the comma in Api? I could not run it with the current code I wrote. I'm using basic auth
.env
API_KEY=...:...
REACT CODE
import {decode as atob, encode as btoa} from 'base-64'
import { API_KEY } from 'dotenv'
import axios from 'axios';
axios.get('...php', { crossdomain: true } , {
headers: {
"Access-Control-Allow-Origin": "*",
'Authorization': 'Basic ' + `${btoa(`${API_KEY}`)}`
}
})
.then(res => { ... })
PHP
$AUTH_USER = '...';
$AUTH_PASS = '...';
if (! empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION']))
{
preg_match('/^Basic\s+(.*)$/i', $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], $AUTH_PASS);
$str = base64_decode($AUTH_PASS[1]);
list( $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] ) = explode(':', $str);
}
$has_supplied_credentials = !(empty($_SERVER['PHP_AUTH_USER']) && empty($_SERVER['PHP_AUTH_PW']));
$is_not_authenticated = (
!$has_supplied_credentials ||
$_SERVER['PHP_AUTH_USER'] != $AUTH_USER || $_SERVER['PHP_AUTH_PW'] != $AUTH_PASS
);
if ($is_not_authenticated) {
header('HTTP/1.1 401 Authorization Required');
header('WWW-Authenticate: Basic realm="Access denied"');
exit;
}

You can either write:
const usernameAndPassword = 'a:b'
axios.get('https://some_url', {
headers: {
Authorization: 'Basic ' + btoa(usernameAndPassword),
},
})
Or,
axios.get('https://some_url', {
auth: {
username: 'a',
password: 'b',
},
})
Both are same; will send exact same request headers:
To read the API_KEY i.e. username password from env file, you should name it as REACT_APP_API_KEY and then you can use it in your code as process.env.REACT_APP_API_KEY.

Related

Laravel passport unauthenticated message

I've been hitting wall for a while now with this, simply I can't get it where is the problem. So I've got backend Laravel and front Vue; logging in is alright, I get token but when I get into one of the routes with auth:api I get "message":"Unauthenticated.". I save token on the front, so should I send it with any request to backend or there is other way around it?
LoginController.php
public function login(Request $request)
{
$login = $request->validate([
'email' => 'required',
'password' => 'required',
]);
if(Auth::attempt($login))
{
return response(['message' => 'Invalid login']);
}
$user = User::where('email', $request->email)->first();
$accessToken = $user->createToken('Laravel Password Grant Client')->accessToken;
return response()->json(['user' => $user, 'access_token' => $accessToken]);
}
api.php
Route::namespace('\\')->middleware('auth:api')->group(function(){
Route::resource('budget', BudgetController::class);
});
user.js
const state = {
token: localStorage.getItem('access_token') || null,
isAuthenticated: localStorage.getItem('access_token') !== null
}
const getters = {
isAuthenticated: state => state.isAuthenticated
}
const actions = {
async retrieveToken({commit}, payload){
console.log(payload)
const response = axios.post(url + '/login', payload)
.then(response => {
const token = response.data.access_token
localStorage.setItem('access_token', token)
commit('setToken', token)
})
}
}
const mutations = {
setToken: (token) => state.token = token
}
Alright, so simply in my second module I used token as a header like this:
const state = {
budget: [],
header: {
headers: {
Authorization: `Bearer ${localStorage.getItem("access_token") || null}`,
withCredentials: true,
"Access-Control-Allow-Origin": "*"
},
}
};
const getters = {
allBudget: (state) => state.budget,
};
const actions = {
async fetchBudget({ commit, state }) {
const response = await axios.get(url, state.header);
console.log(state.header);
commit("setBudget", response.data);
},
};
After that I was getting CORS error so i needed to add two directives at the end of the file xampp\apache\conf\httpd.conf
Header Set Access-Control-Allow-Origin *
Header Set Access-Control-Allow-Headers *

Not able to pass JWT authorization using Angular8

Below php api script given by client when I run into local then Static data storing in api server successfully.
<?php
//creating payload parameters:
$classTitle = 'Demo Class on 3rd April, 2020';
$classInfo = 'This is a demo class scheduled to understand API';
$classDateTime = '2020-11-12 11:30 AM';
$timezone = 'Asia/Kolkata';
$classDuration = 15;
$classRecording = 'yes';
$classAutoStart = false;
$recordingAutoStart = false;
$classVideoRes = 720;
/*xyz.com*/
$apiKey = '12345';
$secretKey = '12345';
// Create token header as a JSON string
$header = json_encode(['alg' => 'HS256','typ' => 'JWT']); // ensure to place first alg part and next typ part
// Create token payload as a JSON string
$payload = json_encode(['classTitle' => $classTitle ,'classInfo' => $classInfo ,'classDateTime' => $classDateTime ,'timezone' => $timezone ,'classDuration' => $classDuration ,'classRecording' => $classRecording ,'classAutoStart' => $classAutoStart ,'recordingAutoStart' => $recordingAutoStart ,'classVideoRes' => $classVideoRes ,'apiKey' => $apiKey]);
// Encode Header to Base64Url String
$base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
// Encode Payload to Base64Url String
$base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload));
// Create Signature Hash
$signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, $secretKey , true);
// Encode Signature to Base64Url String
$base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));
// creating JWT token variable
$jwt_token = $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature;
// creating authorization varibale
$authorization = 'Bearer '.$jwt_token;
?>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript">
$.ajax
({
type: "POST",
url: 'https://xyz/client/schedule',
contentType: 'application/json',
data: JSON.stringify({
"apiKey": "12345"
}),
dataType : 'json',
headers: {
'authorization': '<?php echo $authorization; ?>'
},
success: function(retval)
{
// alert(retval);
console.log(retval);
// var success = retval.success;
}
});
</script>
Directly i pass parameters to above php api then also its not working, my senior told me you have to call above code from angular I wrote code but i am not able to store successfully below is my angular code.
Below is my model class
export class Schedule1 {
classTitle: string;
classInfo: string;
classDateTime: string;
timezone: string;
classDuration: number;
classRecording:string;
classAutoStart: boolean;
recordingAutoStart: boolean;
classVideoRes: number;
constructor() {
}
}
Below is component.ts on button click passing static values
import { Schedule1 } from '../Models/Schedule1.model'
Schedule1: Schedule1 = new Schedule1();
addSchedule(scheduleForm: NgForm): void {
//static data parameter passing
this.Schedule1.classTitle='hi Class on 3rd April, 2020';
this.Schedule1.classInfo= 'This is a demo class scheduled to understand API';
this.Schedule1.classDateTime= '2020-11-12 11:30 AM';
this.Schedule1.timezone= 'Asia/Kolkata';
this.Schedule1.classDuration= 15;
this.Schedule1.classRecording= 'yes';
this.Schedule1.classAutoStart= false;
this.Schedule1.recordingAutoStart= false;
this.Schedule1.classVideoRes= 720;
//const data = JSON.stringify(this.Schedule1);
const data = {
apiKey: "dcbf187d-bdfe-431b-8f60-fa19bf51cd85",
data: JSON.stringify(this.Schedule1)
}
this.subscription = this.userSvc
.fetchData("https: //xyz.com/client/schedule", data)
.subscribe(
data => {
// Data on Success
console.log("data", data);
},
error => {
console.log("error", error);
}
);
}
Below is service.ts
fetchData(url: string, data: any): Observable<any> {
const headers = {
Authorization: "Bearer "+"1234",
"My-Custom-Header": "foobar",
contentType: "application/json"
};
return this.http.post(url, data, {
headers
});
}
in console getting this error.
Can you please try the following changes in your code to check if it works:
First change:
const data = this.Schedule1;
Second change
fetchData(url: string, data: any): Observable<any> {
const headers = {
Authorization: "Bearer "+"dcbf187d-bdfe-431b-8f60-fa19bf51cd85",
"My-Custom-Header": "foobar",
contentType: "application/json"
};
return this.http.post(url, data, {
headers
});
}
I think you need to define the type of request option that you passing to request so you have to use
return this.http.post(url, data, headers: new HttpHeaders({
'Content-Type': 'application/json',
'My-Custom-Header': 'foobar',
Authorization: 'my-auth-token'
}));`
also, you need to import HttpHeaders
import { HttpHeaders } from '#angular/common/http';
Try using unblock cors extension on your browser and check it again
you are getting this error 'https ://xyz.com/client/schedule' from origin 'localhost:4200' has been blocked by CORS policy because server and client is running on different host, either you have to run server locally or try this,
open chrome using this command and check browser network tab
chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security
Did you try to setup a config file "src/proxy.conf.json"
{
"/api/*": {
"target": "http://localhost:4200",
"secure": false,
"logLevel": "debug"
}
}
and have your "angular.json" point to the config file
"architect": {
"serve": {
"builder": "#angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "your-application-name:build",
"proxyConfig": "src/proxy.conf.json"
},
this will only be for testing purposes (since you have no access to the server, right ?)

How can I connect my angular-nativescript app to a DB for a login?

I'm trying to create an app through NativeScript and Angular which will manage the working hours of the employees for a company.
So, I have to set up a login page and there's my problem: I linked a function on the tap of the LOGIN button and, after clicking on it, I send username and password to a service where I'm trying to connect to and end-point (mypath/api/auth.php).
In this php file I set up the DB connection and a SELECT query which receive username and password as a $_POST function. But, now, when I tap on my LOGIN button I got an alert with [Object Object] even if the credentials are right or wrong.
I'm a beginner in both NativeScript and Angular.
My PHP user verification function:
$username = $_POST["username"];
$password = $_POST["password"];
$conn = getDB();
$hash_pwd = hash('sha256', $password);
$stmt = $conn->prepare("SELECT * FROM dipendenti WHERE cod_fiscale=:username AND password=:password");
$stmt->bindParam("username", $username,PDO::PARAM_STR) ;
$stmt->bindParam("password", $hash_pwd,PDO::PARAM_STR) ;
$stmt->execute();
$count=$stmt->rowCount();
$data=$stmt->fetch(PDO::FETCH_OBJ);
closeDB($conn);
return json_encode($data);
My user.service.ts file:
import { Injectable } from "#angular/core";
import { HttpClient, HttpHeaders, HttpResponse } from "#angular/common/http";
import { Observable, throwError } from "rxjs";
import { catchError, map, tap } from "rxjs/operators";
import { Auth } from "./auth.model";
import { Config } from "../config";
#Injectable()
export class AuthService {
constructor(private http: HttpClient) { }
login( user: Auth) {
if(!user.codFiscale || !user.password) {
return throwError("Devi inserire sia codice fiscale sia la tua password per accedere");
}
return this.http.post(Config.apiUrl + 'api/auth.php',
JSON.stringify({
username: user.codFiscale,
password: user.password
}),
{
headers: this.getCommonHeaders()
}).pipe(
map(response => response),
catchError(this.handleErrors)
);
}
getCommonHeaders() {
return {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
}
}
handleErrors(error: Response) {
console.log(JSON.stringify(error));
return throwError(error);
}
}
My function triggered on the button tap:
submitLogin() {
if(this.isLoggingIn) {
this.authService.login(this.user).subscribe(
() => {
this.router.navigate(["/home"]);
},
(exception) => {
if(exception.error && exception.error.description) {
alert(exception.error.description);
} else {
alert(exception.error);
}
}
);
}
}
Is there something I have forgotten?
i do it in nativescript-vue, maybe you need to adjust for angular.
I use axios plugin for that, it works for ns-angular too, i just don't know how to config it on angular... but the code is this:
async submitLogin() {
const data = {
email: this.user.email,
password: this.user.password
};
try {
const res = (await api.post(this.getApiUrl+"/app/services/login.php", data)).data;
if (res.code === 200){
//handle login success
}
else if (res.code === 500){
//handle login fail
}
}
catch (e) {
console.error("Connection error: ", e);
}
},
where api.post is:
post(url, request, config) {
return axios.post(url, request, config)
.then((response) => Promise.resolve(response))
.catch((error) => Promise.reject(error));
},
Edit: The res.code is a custom response that i send in the response, it's not default!

JSON Object returned on Http error in Nodejs, fetch

I am using Laravel apis for my project. The API is working fine when I use curl to access it.
curl -H "Content-Type: application/json" -X POST -d '{"username":"xyz","password":"xyz", "filterZip":"123123"}' http://localhost:8080/api/signup {"error":{"message":"User with specified email address already started sign up process, but did not finished it. Please sign in regulary to continue sign up process.","errorCode":"020102"}}
However when I call if from nodejs app. I am unable to access the error Json Object from the response.
From Nodejs I am calling my laravel API
fetch(API_URI + '/signup', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(requestBody)
}).then(checkResponse)
.then(response => {
userData = response.data;
req.session.user = {
username: userData.displayName || userData.email,
data: userData,
auth: authData
};
req.session.resession = true; // tell ssrCache to act
return res.status(200).json(req.session);
})
.catch(status,error) => {
console.log('Request failed', error);
req.session.user = null;
req.session.resession = true; // tell ssrCache to act
return res.status(200).json(req.session);
});
});
const checkResponse = (response) => {
if (response.status >= 200 && response.status < 300) {
return response.json();
}
var error = new Error(response);
error.code = object.error.errorCode;
throw error;
}
On the Laravel API end following code is used to return response.
public function respondError($errorId, $statusCode, $message = 'Unknown') {
$this->setHttpStatusCode($statusCode);
$errorCode = ErrorHelper::generateErrorCode($this->controllerErrorId, $this->methodErrorId, $errorId);
if (API_LOG_ERROR_CODES) { ErrorHelper::logErrorCode($errorCode, $message); }
return $this->respond([
'error' => [
'message' => $message,
'errorCode' => $errorCode
]
]);
}
public function respond($dataForJson, $headers = []) {
return response()->json($dataForJson, $this->getHttpStatusCode(), $headers);
}
OK I figured it out.
The issue was with my handling of response. In the response I was not converting the response to response.json() whenever the response.status was greater than 300. once I did that I was able to extract the required json object. Following is a better approach for handling response.
const checkResponse = (response) => {
if (response.status >= 200 && response.status < 300) {
return response.json();
}
return reject(response.status, response.json());
}

Error handling in ionic2/ Angular2

Trying to integrate APIs built in Laravel 5.4 with ionic 2 and struggling handle the error
What I want to do:
Authenticate the login using Laravel Password service ( OAuth2 ).
Once authenticated, it would return the access token.
Access Token is passed in the header in a GET API call to receive the
user details.
I am able to #1 and #2 but got stuck at #3.
Here is my code of login.ts
public login() {
this.showLoading();
this.auth.login(this.loginCredentials).subscribe(allowed => {
if (allowed) {
setTimeout(() => {
this.loading.dismiss();
this.nav.setRoot(HelloIonicPage)
});
} else {
this.showError("Access Denied");
}
},
error => {
this.showError(error);
});
}
auth is a service provider, that has login method.
//Function to get access token
public login(credentials) {
if (credentials.email === null || credentials.password === null) {
return Observable.throw("Please insert credentials");
} else {
return Observable.create(observer => {
var link = 'http://localhost/XXX/public/oauth/token';
var vars = {
password: "XXX",
username: "XXXXXX",
grant_type: 'password',
client_id: "XXXXX",
client_secret: 'XXXXXX',
scope: ''
}
this.http.post(link, vars)
.map(res => res.json())
.subscribe(
data => { let user = this.getUserFromAccessToken(data);
console.log(user);
observer.next(user);
},
err => { observer.error(err.json()); }
() => {
console.log('Completed..');
}
);
});
}
}
//Function to get user from the accessToken
private getUserFromAccessToken(oAuthData) {
let headers = new Headers({ 'Content-Type': 'application/json','Accept': 'application/json','Authorization': 'Bearer ' + oAuthData.access_token });
let options = new RequestOptions({ headers: headers });
let link = 'http://localhost/XXXX/public/api/v1/user';
return this.http.get(link, options)
.map(res => res.json())
.subscribe(
data => this.currentUser = data.user,
err => this.error = err
);
}
currentUser and error are defined as properties of the AuthService class.
How should I ensure that an error is thrown either in case the access token is not returned or user is not returned from the access token.

Categories