How can I make Handshake between client and https server - android

I'm working on project that requires secure connection between Client (which is Android Device) and Server which is (Nestjs app)
and for generating my certificate I'm using openSSl this is the link I followed
Link : Tuto openSSL
I configured main.ts as shown below :
import { NestFactory } from '#nestjs/core';
import { NestExpressApplication } from '#nestjs/platform-express';
import { AppModule } from './app.module';
import * as fs from 'fs';
const httpsOptions = {
key: fs.readFileSync('certssl/CA/localhost/localhost.decrypted.key'),
cert: fs.readFileSync('certssl/CA/localhost/localhost.crt'),
};
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule, {
httpsOptions,
});
await app.listen(443);
}
bootstrap();
and this is my gateway.ts file
import { Logger } from '#nestjs/common';
import {
MessageBody,
OnGatewayConnection,
OnGatewayDisconnect,
OnGatewayInit,
SubscribeMessage,
WebSocketGateway,
WebSocketServer,
WsResponse,
} from '#nestjs/websockets';
import { Server, Socket } from 'socket.io';
#WebSocketGateway({
cors: {
origin: '*',
transports: ['polling', 'websocket'],
},
})
export class AppGateway implements OnGatewayInit, OnGatewayDisconnect {
handleDisconnect(client: any) {
this.logger.log(`Disconnected ${client.id}`);
}
#WebSocketServer() server: Server;
private logger: Logger = new Logger('GatewayApp');
afterInit(server: Server) {
this.logger.log('Initiate Gateway');
}
handleConnection(client: Socket) {
client.emit('connection', 'Success from server');
this.logger.log(`connected ${client.id}`);
}
#SubscribeMessage('events')
handleEvent(#MessageBody() data: string): string {
this.logger.log(data);
return 'data recieved';
}
}
Finally I get This result
Image Result
Everything works fine :)
In case you want information of my certificate :
-----BEGIN CERTIFICATE-----
MIIECzCCAvOgAwIBAgIUICWr5H/qokSSpTlzE+tEnzgbkTcwDQYJKoZIhvcNAQEL
BQAwgZIxCzAJBgNVBAYTAlROMQ4wDAYDVQQIDAVUdW5pczEQMA4GA1UEBwwHTGUg
a3JhbTEUMBIGA1UECgwLbXMtdGVjaHNvZnQxCzAJBgNVBAsMAm1zMRIwEAYDVQQD
DAlkZXZlbG9wZXIxKjAoBgkqhkiG9w0BCQEWG2xhc3NvdWVkLnNrYW5kZXJyQGdt
YWlsLmNvbTAeFw0yMjA0MDExMzA0NTNaFw0zMjAzMjkxMzA0NTNaMIGSMQswCQYD
VQQGEwJUTjEOMAwGA1UECAwFVHVuaXMxEDAOBgNVBAcMB0xlIGtyYW0xFDASBgNV
BAoMC21zLXRlY2hzb2Z0MQswCQYDVQQLDAJtczESMBAGA1UEAwwJZGV2ZWxvcGVy
MSowKAYJKoZIhvcNAQkBFhtsYXNzb3VlZC5za2FuZGVyckBnbWFpbC5jb20wggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDtbHpyuI67tqwKDopaDsO5sDCk
l/peIJwBlzR/Ct7PsBrsb2PlPquf+mJAhze0L6qlvhNYYxFRjjeYLFm56yStEya1
hHpUQIEoLwiHkZtZjOsZaivSHOUk0RqicxYsr8K4Xc9kKiZunBEZMZhOSgXADpbM
OKmdWeBXgptx9u6t7OYnOtO/P5m66d4LQr6CypdgBv1k4c0KdOjeRpQnDInsgXf8
EM050Avf/mA9klg3c+gbuOtMPiDD8x5t5L3/EL6cEe1uTjiZ0VFVM28CU8wqScE4
OHSOHlAThYxO6In7znQB045ufj+KPvXkPRTKvWWA4bNpTWK8tSzPgDo5eFdtAgMB
AAGjVzBVMB8GA1UdIwQYMBaAFHLNCdi+lgexURmmUhGZL6BH6CZXMAkGA1UdEwQC
MAAwCwYDVR0PBAQDAgTwMBoGA1UdEQQTMBGCCWxvY2FsaG9zdIcEfwAAATANBgkq
hkiG9w0BAQsFAAOCAQEAGX/57t23Il/lPt8ka8CCyFx5jL2+aoxGEFp0yF1xLNhm
adL05I/ShG9Ux7J6NlbX9uxKLmb3aZ3zpUtnWFIEgl883JfgeyMP/hVzTPKdYcI4
ff3O2cb3OdlxlEXv4jXTUyyzlX2iNVD2M0AsGFsscUP5EcWAV/T88vLKJpb68jG7
ihNP2insYw9TtxEVl1Qm0HcOaFItje/B+78YeJrbN8dM+I1hLp5FVBeIiPIzEnvJ
eSUhI2gKfwEMREEFsUe9A6NOwnsZPIvATXDnN7QQgGyd5rOAqzOlZGl6UnoHwtVh
1xpYMMdjrkbnIpgxNlRYTSf8hqd4y2HAdZtpzfVLCQ==
-----END CERTIFICATE-----
Link for testing : https://8gwifi.org/PemParserFunctions.jsp
Just change **Sample file** to **crt** and copy my public key inside the box to get the informayion
My problem
When I give my local ip which is starts by 192.168.x.x to the client(android studio in same nework) we get time out failed to connect
Could any one help me I'm stuck since one month

Related

status: -1: There was an error with the request: no protocol:

I'm trying to do an HTTP request on an android emulator, I built with ionic and compiled with capacitor.
I'm using the HTTP module from #ionic-native/http/ngx. I have a per-existing interceptor that I used when I was making requests using the HttpClient from #angular/common/http. This is what that interceptor looks like:
export class InterceptorService implements HttpInterceptor {
protected apiUri = environment.API_URL;
constructor(
private authSvc: AuthService,
private toastCtrl: ToastController
) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const url = this.apiUri + req.url;
const token = this.authSvc.getStorageToken();
if (token) {
req = req.clone({
url,
headers: req.headers.set('Authorization', `Bearer ${token}`)
});
}
return next.handle(req).pipe(
map((event: HttpEvent<any>) => {
return event;
}),
catchError( (err: HttpErrorResponse) => {
let errMessage = err.error.message;
if (err.error.title) {
errMessage = err.error.title;
}
if (!errMessage) {
errMessage = err.error;
}
this.presentToast(err.status, errMessage);
return throwError(err);
})
);
}
async presentToast(status: number, message: string) {
const toast = await this.toastCtrl.create({
message,
buttons: ['OK']
});
await toast.present();
}
}
My auth-service:
/* service request to get a toke */
getAuthToken(model: IGetTokenModel) {
return this.http.post('/user/token', model, {});
}
The environment.API_URL is the url to my API on my local machine.
I'm guessing the no protocol means I'm posting data to /user/auth instead of the full which includes the hostname. But I'm not sure of this. However, if that were the case, how would I refactor my interceptor so that it works as expected with the #ionic-native/http/ngx?
Finally have this sorted. I was pointing to localhost inside the emulator. Turns out that requests made inside the emulator have to point to http://10.0.2.2:PORT.
I suppose localhost in a sense still point to the emulator itself.

Ionic angular http post not working on device but works fine on browser

I'm working on an ionic-angular app and post request is working fine when tested on browser using ionic serve but when excecuted on anroid device or emulator, the request doesn't work.
The backend is a rest api using slim php and xampp on windows server
The response for the request in android device is:
{"headers":{"normalizedNames":{},"lazyUpdate":null,"headers":{}},"status":0,"statusText":"Unknown Error","url":"http://<>/ws_login.php/login","ok":false,"name":"HttpErrorResponse","message":"Http failure response for http://<>/ws_login.php/login: 0 Unknown Error","error":{"isTrusted":true}}
My login code looks like:
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { HttpClientModule, HttpClient, HttpHeaders } from '#angular/common/http';
import { AuthConstants } from '../config/auth-constants';
import { ToastService } from './../services/toast.service';
import { LoadingService } from './../services/loading.service';
import { StorageService } from './../services/storage.service';
import { environment } from '../../environments/environment';
#Component({
selector: 'app-login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {
data = {
user : '',
pass : ''
}
constructor(
public http: HttpClient,
private router: Router,
private toastService: ToastService,
private loadingService: LoadingService,
private storageService: StorageService
) { }
ngOnInit() {
this.storageService.get(AuthConstants.AUTH).then(
data => data?this.router.navigate(["home"]):null
)
}
login() {
var headers = new HttpHeaders();
headers.append("Accept", 'application/json');
headers.append('Content-Type', 'application/json' );
const requestOptions = { headers: headers };
if(this.data.user == "" || this.data.pass == "")
return this.toastService.presentToast("Debe completar ambos campos", "danger");
this.loadingService.showLoading("Iniciando sesión");
console.log(environment.apiUrl+'ws_login.php/login');
this.http.post(environment.apiUrl+'ws_login.php/login', this.data, requestOptions).subscribe(
resp => {
this.loadingService.hideLoading();
if(resp){
if(resp['error'] == 1)
this.toastService.presentToast(resp['mensaje'], "danger");
else{
this.storageService.store(AuthConstants.AUTH, 1);
this.toastService.presentToast("Sesión iniciada con éxito", "success");
this.router.navigate(["home"]);
}
}
else
this.toastService.presentToast("Error de red", "danger");
},
error => {
this.data.user = JSON.stringify(error);
this.loadingService.hideLoading();
this.toastService.presentToast("Error de red", "danger");
}
);/*
console.log(AuthConstants.AUTH);
AuthConstants.AUTH = {id: 1};*/
//this.router.navigate(["home"]);
}
}
I also test the api using a rest app on device and the same url answers without problem.
I added android:usesCleartextTraffic="true" to androd manifest and was not the solution.
Here mi ionic info
Ionic:
Ionic CLI : 6.3.0 (C:\Users\Manu\AppData\Roaming\npm\node_modules\#ionic\cli)
Ionic Framework : #ionic/angular 5.0.7
#angular-devkit/build-angular : 0.803.26
#angular-devkit/schematics : 8.3.26
#angular/cli : 8.3.26
#ionic/angular-toolkit : 2.2.0
Capacitor:
Capacitor CLI : 2.0.0
#capacitor/core : 2.0.0
Utility:
cordova-res : 0.11.0
native-run : 0.3.0
System:
NodeJS : v12.16.1 (C:\Program Files\nodejs\node.exe)
npm : 6.13.4
OS : Windows 10
Thanks!
Since the error says that you are posting to http://<>/ws_login.php/login, I guess that there is a mistake in your environment variable apiUrl, when you deploy to mobile.
If you serve the app on your developer machine, it will take the environment.ts to get the variables. Maybe you build the app for your phone in production and thus don't get the right environment variables (since Ionic then uses environment.prod.ts?
Apparently angular httpClient has some issues when executed on native devices and emulators, my solution was migrating the request to ionic native http.
Thanks for the help!
you can try ionic advance HTTP with mobile device https://ionicframework.com/docs/native/http, but it does not work with web browsers it only works in the mobile device. so you can try solution as
check the platform and return HTTP service object as per users platform.
example:
if user platform==web then return Angular HttpClient
else if user platform==Android/Ios then return Advnace Http object.
or you can use this code directly which has a wrapper around HTTP service,
import { Injectable } from '#angular/core';
import { Platform } from '#ionic/angular';
import { HttpClient } from '#angular/common/http';
import { HTTP } from '#ionic-native/http/ngx';
import { from, observable, Observable, of } from 'rxjs';
import { environment } from './../../environments/environment';
import { map, catchError } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class HttpService {
constructor(private platform: Platform, private httpclient: HttpClient, private http: HTTP) {
}
HttpRequest(method: 'POST'|'GET', url: string, requestBody: any): any
{
url = environment.serverBaseUrl + url;
const headers = {};
if (this.platform.is('ios') || this.platform.is('android') || this.platform.is('mobile'))
{
if (method === 'POST')
{
console.log('Advance_HTTP_POST');
return from(this.http.post(url, requestBody, headers)).pipe(map((data: any) => JSON.parse(data?.data)));
} else if (method === 'GET')
{
console.log('Advance_HTTP_GET');
return from(this.http.get(url, {}, headers)).pipe(map((data: any) => JSON.parse(data?.data)));
}
} else {
if (method === 'POST')
{
console.log('HTTPClient_HTTP_POST');
return this.httpclient.post(url, requestBody, {headers});
} else if (method === 'GET')
{
console.log('HTTPClient_HTTP_GET');
return this.httpclient.get(url, {headers});
}
}
}
}
I was facing the same issue. In my case, I was doing a PROD build and the environment.prod.ts file didn't have the hosted API links.
I followed the below steps and my issue was resolved:
Update the environment.prod.ts file links to your hosted api.
Build your SPA to the www (any folder configured in your app) folder with the required configuration.
Add platform if it is the first instance - npx cap add android
Copy resources to the platform code - npx cap copy
Update the android app if any plugin is added - npx cap update
Open android app - npx cap open android
Check the app in the emulator and test API response.
BINGO! Hope this helps someone in need.

Ionic 4 android app not connecting to local node js server when running on real android device

I am trying to implement a client-server communication for my Ionic 4 android app. I have a local node js server implementation on my pc and I am using socket.io to establish the communication. The problem is that when I am running the app on browser or on emulator the communication between the app and local server is ok but when I am trying to run the app on a real android device (samsung galaxy s9+) the app cannot connect to the local server. More specific the message 'User Connected' is not appeared on the server console to indicate that app is connected to the server and therefore user never gets back his userid.
Can anyone help me to find out why?
Server side
index.js
let app = require('express')();
let server = require('http').createServer(app);
let io = require('socket.io')(server);
// Allow CORS support and remote requests to the service
app.use(function(req, res, next)
{
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,Authorization');
next();
});
// Set up route
app.get('/', (req, res) =>
{
res.json({ message: 'You connected to panic Shield server' });
});
var port = process.env.PORT || 8080;
server.listen(port, function(){
console.log('listening in http://192.168.x.x:' + port);
});
const uuidv4 = require("uuid/v4");
// User connected to the server
io.on('connection', (socket) => {
console.log('User Connected');
socket.on('disconnect', function(){});
socket.on('set-credentials', (credentials) => {
let userId = uuidv4();
...
// server informs user for his unique id
socket.emit('your user id', userId);
...
}
});
Client side
app.module.ts
import { SocketIoModule, SocketIoConfig } from 'ngx-socket-io';
const config: SocketIoConfig = { url: 'http://192.168.x.x:8080', options: { secure: true } };
#NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [
BrowserModule,
IonicModule.forRoot(),
AppRoutingModule,
HttpClientModule,
SocketIoModule.forRoot(config)
],
...
home.page.ts
import { Socket } from 'ngx-socket-io';
constructor(private socket: Socket) { }
async ngOnInit() {
this.socket.connect();
...
}
async connectToServer(name, surname, gender, speech) {
const str = name.concat(' // ').concat(surname).concat(' // ').concat(gender).concat(' // ').concat(speech);
this.socket.emit('set-credentials', str);
this.socket.on('your user id', (data) => {
this.userId = data.toString();
// save the userId
set('userId', this.userId);
// Refresh the page
window.location.reload();
});
}
I found the problem. In my case, the firewall of my pc doesn't allow any other device on local network connect to the server. When I turned off the firewall the connection between client-server was established!

Vue router doesn't work on some Androids. Is there a workaround?

I am building an app that is using Google authentication through firebase and that needs to redirect the user from a login.vue component to an /hello path upon successful authentication.
I have first tried doing it the normal vue way:
this.$router.replace('/hello')
only to realise my Samsung Galaxy J5 wasn't having it...
All is working on other devices and browsers (so far) using the normal Vue routing tools but on some Android devices Vue is refusing to collaborate. I have read here some Android versions do not like the way the Vue dynamic routing transpiles to vanilla JS so I am attempting the following (still, no success).
This is my code on the created hook of component login.vue when Google auth (with redirection, not pop up) returns to it:
created() {
firebase.auth().getRedirectResult().then(result => {
var user = result.user;
if (user) {
var ua = navigator.userAgent.toLowerCase();
var isAndroid = ua.indexOf("android") > -1;
if(isAndroid) { // NOT WORKING (stays on Login.vue although I am sure it's detecting it's an Android)
window.location.href = window.location.host + '/hello';
} else {
this.$router.replace('/hello') // this work perfectly
console.log(window.location.host + "/hello" ); // this is returning the intended address: localhost:8080/hello
}
} else {
toastr.warning("Oops something went wrong on login!");
}
}).catch(error => {
// dealing with redirection result errors from Google Authentication
});
This is my index.js routing file (I am doing some route guarding here so it may be useful for you to get a bigger picture if I paste the file):
import Vue from 'vue'
import Router from 'vue-router'
import firebase from '../firebase-config'
import {store} from '#/store/store'
import hello from '#/components/hello'
import login from '#/components/login'
import landing from '#/components/landing'
Vue.use(Router)
let router = new Router({
mode: 'history',
routes: [
{
path: '*',
redirect: '/landing'
},
{
path: '/',
redirect: '/landing'
},
{
path: '/landing',
name: 'landing',
component: landing
},
{
path: '/login',
name: 'login',
component: login
},
{
path: '/hello',
name: 'hello',
component: hello,
meta: {
requiresAuth: true
}
},
],
})
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
firebase.auth().onAuthStateChanged(function(user) {
if (!user) {
next({
path: '/landing'
})
} else {
next()
}
});
} else {
next()
}
})
export default router
Any thoughts?

Ionic2 proxyUrl does not work on device

While running the app on device it does not get the api url
it does not fetch the url
I have used following coding
{
"v2": true,
"typescript": true,
"proxies": [
{
"path": "/api",
"proxyUrl": 'api url here'
}
]
}
Please give any suggustions
The proxy service is meant for testing in the browser to avoid the No 'Access-Control-Allow-Origin' header is present on the requested resource error when using an external API. But this is not a problem on devices and therefor there is no need for this proxy service. So, on devices use direct calls to your API url in stead of calls to http://localhost:8100.
If you want to test on both a device and browser, just check if Cordova is available (and so you're on a device) and then define which URL to use. Something like this:
import {Injectable} from '#angular/core';
import {Headers, Http} from '#angular/http';
import {Platform} from 'ionic-angular';
import 'rxjs/add/operator/toPromise';
import ...
#Injectable()
export class AccessService {
private headers = new Headers({'Content-Type': 'application/json'});
private apiUrl = '/v1/';
constructor(private http: Http,
public platform: Platform) {
if (this.platform.is('cordova')) { // <<< is Cordova available?
this.apiUrl = 'https://api.instagram.com/v1/';
}
}
login(username: string, password: string): Promise<string> {
let postParams = {
username: username,
password: password
};
return this.http
.post(this.apiUrl + 'login', postParams, this.headers)
.toPromise()
.then(response => response.json().devicetoken as string)
.catch(this.handleError);
}
}
...
}

Categories

Resources