how to use http2 in loopback 4 application? - loopbackjs

We are planning to implement http2 in a loopback 4 application. We had used http, socket servers but never http2.
What is the procedure to use http2 in my application?

Here's what you have to do in your existing app:
Step 1: Install spdy
npm i spdy
Step 2: Configure index.ts
Change your main function in src/index.ts with this:
import spdy from "spdy";
export async function main(options: ApplicationConfig = {}) {
// specify cert and key file paths for SSL
const serverOptions: spdy.ServerOptions = {
key: fs.readFileSync(
path.join(__dirname, '..', 'keys', 'localhost-privkey.pem'),
),
cert: fs.readFileSync(
path.join(__dirname, '..', 'keys', 'localhost-cert.pem'),
),
};
// setting listenOnStart to false will not start the default httpServer
options.rest.listenOnStart = false;
// Replace YourApplication with your class
const app = new YourApplication(options);
await app.boot();
await app.start();
// create server
const server = spdy.createServer(serverOptions, app.requestHandler);
// to avoid process exit on warnings
server.on('warning', console.warn);
server.listen(3000, () => {
console.log('Listening on https://localhost:3000/');
});
return app;
}
All we're doing in the above code is, preventing the default http server from being started and starting the server using spdy with loopback's request handler app.requestHandler that will be used for all incoming request.
Check out this pastebin containing entire index.ts file content after the changes.
To generate certificate and keys for localhost use:
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
-keyout localhost-privkey.pem -out localhost-cert.pem
You may need to allow self-signed certificates in Chrome as well for /explorer to work as expected.
And that's it, you can now run your app, and enjoy the power of http2 :)
Blog Post: https://shubham-web.medium.com/how-to-use-http2-in-loopback-4-applications-5e83881c7b38

Related

Custom "statusMsg" not working as expected

After adding the following adaptive authentication script, if the username is not according to the format I should be getting the custom status message saying, Access Denied, invalid username format. But instead I get the default status message, Something went wrong during the authentication process. Please try signing in again.
function onLoginRequest(context) {
executeStep(1, {
onSuccess: function(context) {
var user = context.currentKnownSubject;
if(user!= null && user.username != null && !user.username.equals('')) {
Log.info("username: " + user.username);
} else {
sendError('',{'status':'AUTHENTICATION USERNAME ERROR', 'statusMsg': 'Access denied, invalid username format.'});
}
}
});
}
In addition, I get the following error in the wso2carbon.log file as well.
TID: [-1234] [authenticationendpoint] [2022-10-05 15:44:12,715] [37951f7d-8240-48d4-ad4f-1d4c8a6a3ec4] ERROR {org.wso2.carbon.identity.application.authentication.endpoint.util.AuthContextAPIClient} - Sending GET request to URL : https://dev.wso2istemp.com/api/identity/auth/v1.1/data/AuthenticationError/0b0efc37-819d-4b39-85b2-517126c3c9cb, failed. java.io.IOException: Server returned HTTP response code: 401 for URL: https://dev.wso2istemp.com/api/identity/auth/v1.1/data/AuthenticationError/0b0efc37-819d-4b39-85b2-517126c3c9cb
...
org.wso2.carbon.identity.application.authentication.endpoint.util.AuthContextAPIClient.getContextProperties(AuthContextAPIClient.java:70)
at org.apache.jsp.retry_jsp._jspService(retry_jsp.java:194)
...
org.wso2.carbon.ui.filters.cache.ContentTypeBasedCachePreventionFilter.doFilter(ContentTypeBasedCachePreventionFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
...
org.wso2.carbon.identity.application.authentication.endpoint.util.filter.AuthenticationEndpointFilter.doFilter(AuthenticationEndpointFilter.java:190)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
...
The <IS_HOME>/repository/conf/deployment.toml configurations for [server] are as follows.
[server]
hostname = "dev.wso2istemp.com"
node_ip = "127.0.0.1"
base_path = "https://$ref{server.hostname}:${carbon.management.port}"
What is the reason for the following issue in the wso2carbon.log and why the custom status message is not shown properly?
When the adaptive authentication script is running, the values are passed to the Identity Server(IS) encrypted. In above case, the encrypted data chunk is passed to the IS,
https://dev.wso2istemp.com/api/identity/auth/v1.1/data/AuthenticationError/24e56d99-9494-4989-a3e2-4008b73ebd9b
with the last segment of the URL is being the data chunk. When the server tries to get that data chunk with a GET request, java.io.IOException: Server returned HTTP response code: 401 for URL which is the code for unauthorized is thrown. Since that data chunk is not properly received, the default status message is shown instead of the custom status message. The steps to resolve this are given below.
First clarify whether the dev.wso2istemp.com which you were using is not mapped with the localhost in /etc/hosts file.
Go to <IS_HOME>/repository/conf/deployment.toml file and check for the following configuration [identity.auth_framework.endpoint] and check whether the mutual SSL is set to false via mutual_ssl_manager_enabled=false
If so, enable that by commenting the mutual_ssl_manager_enabled=false, since using mutual SSL is recommended for IS. If you go to the <IS_HOME>/repository/resources/conf/default.json file, you can notice that the default value for mutual_ssl_manager_enabled is true
In a multi-node situation, the above error can occur if the mutual SSL is not enabled, If that does not resolves the issue, then you have to check whether the internal_hostname has been set properly so that the internal API calls are being sent properly.
To do that, if you have not added the following configuration to <IS_HOME>/repository/conf/deployment.toml file, you can check whether it has been properly applied to the <IS_HOME>/repository/conf/identity/identity.xml by checking for <ServerHostName>localhost</ServerHostName>
[server]
internal_hostname="localhost"
If you are using a multi-node deployment, this localhost value should be added to the SAN for the certificate when the certificate is generated (-ext SAN=dns:localhost)
keytool -genkey -alias newcert -keyalg RSA -keysize 2048 -keystore newkeystore.jks -dname "CN=dev.wso2istemp.com, OU=Is,O=Wso2,L=SL,S=WS,C=LK" -storepass mypassword -keypass mypassword -ext SAN=dns:localhost
But if you are using a single node you can add the following configuration to the deployment.toml and check whether it resolves things. (In single node case the internal_hostname should be similar to hostname)
[server]
hostname = "dev.wso2istemp.com"
internal_hostname = "dev.wso2istemp.com"
If that is not working[https://github.com/wso2/product-is/issues/11878] then go to <IS_HOME>/repository/deployment/server/webapps/authenticationendpoint/WEB-INF/web.xml and uncomment the following commented snippet.
<!--context-param>
<param-name>AuthenticationRESTEndpointURL</param-name>
<param-value>https://localhost:9443/api/identity/auth/v1.1/</param-value>
</context-param-->
This might route the internal_hostname being reflected on the request since the internal API calls are blocked when hostname of the server being replaced instead of the internal_hostname for the internal API calls(https://dev.wso2istemp.com/api/identity/auth/v1.1/data/AuthenticationError/24e56d99-9494-4989-a3e2-4008b73ebd9b).

ESP32 MQTT with TLS not working with NATS MQTT

Hi i have a project about connect ESP32 to NATS via MQTT
After I try --insecurity it work normally.
But when I add TLS it doesn't work in my ESP32, i also try with Python it work normally with my self-signed SSL certificate.
I already find solution from here but it not work: https://github.com/espressif/arduino-esp32/issues/5021
My idea code get from here: https://github.com/debsahu/ESP-MQTT-AWS-IoT-Core/blob/master/Arduino/PubSubClient/PubSubClient.ino
Is MQTT TLS in ESP32 not work with self-signed cert or I done something wrong ?
Cert TLS:
"-----BEGIN CERTIFICATE-----\n"
"MIID8TCCAtmgAwIBAgIUfceZXKK1JIqHi57rc98EBmJoy1kwDQYJKoZIhvcNAQEL\n"
"BQAwgYcxCzAJBgNVBAYTAlZOMRAwDgYDVQQIDAd2aWV0bmFtMRAwDgYDVQQHDAd2\n"
"aWV0bmFtMQ4wDAYDVQQKDAVwZWNvbTENMAsGA1UECwwEdGVzdDENMAsGA1UEAwwE\n"
"bXF0dDEmMCQGCSqGSIb3DQEJARYXY3B0cHJpY2UxMjNAb3V0bG9vay5jb20wHhcN\n"
"MjIxMTAzMDgxMDEzWhcNMjMxMTAzMDgxMDEzWjCBhzELMAkGA1UEBhMCVk4xEDAO\n"
"BgNVBAgMB3ZpZXRuYW0xEDAOBgNVBAcMB3ZpZXRuYW0xDjAMBgNVBAoMBXBlY29t\n"
"MQ0wCwYDVQQLDAR0ZXN0MQ0wCwYDVQQDDARtcXR0MSYwJAYJKoZIhvcNAQkBFhdj\n"
"cHRwcmljZTEyM0BvdXRsb29rLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\n"
"AQoCggEBALRTuKn8m1QuFJI3THb2rkEiKPHD/cdRs/E1Vb96GIBSy4D/s8vJ2OWd\n"
"GHlbLK557OpAH7JrRg6tVEVVr3293u8imwDIcNyOHlBYWSO/DBKGXsoCbOL1u6Gd\n"
"zAn/G+96eX3RUIHRbBF/rE6DZS5Y1Piq7FwdaReHSZhMPB+UMB4xUEC3pC6CzqFt\n"
"xjudk9zT5VpR60XiJAls3YtYpUu4zRZUw2Sb1ZsPmT555QFYbOcF4XlC82MVi/o3\n"
"M91LJ8DyiOvNWxuioIT2frEyIXaTleug3Ev0ALiu8ug9/v/zTWZWq3KA98HZJcm+\n"
"Hr8dChlMewpMpabEi1e0twlzTPw9QyMCAwEAAaNTMFEwHQYDVR0OBBYEFE3SQ0F5\n"
"yzsBkHUcFp/KucgyGHpWMB8GA1UdIwQYMBaAFE3SQ0F5yzsBkHUcFp/KucgyGHpW\n"
"MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAC+pjnAd9c71DfCv\n"
"RUMvYg93mraaqtoEw22ggtT9AfIZfI+o8L5Nxk5us+9k9IBEP4hi6DHtnFxqfFt8\n"
"YkzNNDMTDvLfg/1INUwg8yBYS9Z2+puoPlPTvaxOJiuz2+DkYV/LnUdTolKPqYrO\n"
"IBIbmwMNz0Bqn1XZ7Mjx9U7p+A2N/87NGl3fo0I0tWBRSGXFZB7IYipgCPQG5Eb+\n"
"ZL9vrgFuNJhAVALvDfwKxCX6VdyNpthAMA7cmra+s0/weZsfQLyU2TtnsIg0uoq0\n"
"L4sTpL6Q7Fr4UpOJrezNx/kuHHxBBKhJtlz4Tcaw/OKu/h2g5jjHFT9yN86KUxSY\n"
"PDH47kk=\n"
"-----END CERTIFICATE-----\n";
// You can use x.509 client certificates if you want
const char *test_client_key =
"-----BEGIN RSA PRIVATE KEY-----\n"
"MIIEogIBAAKCAQEAllaf/na5h3yDr2zoYsYGGqt/d93/AAUTculGTXdGGbRwyHue\n"
"b0BaMeX+ht9siZ82iuaZ/5mJ/kq8WVwlrkegOAvU7SQDoALPM7VLMLSMbnn2Wqog\n"
"WE48TkWU0WddtTFHVDGLX8zMC1TQ1VKyVzp2QtCW9RPJNun9CVJSoZ34uM5hBL1f\n"
"7MY7t/QsDYi14UtULDsSnVz+tDLiPrBkZOPEVhopCH1gvljcDTcICfawyK5nlCKc\n"
"AnUWTHEUzf89WCJkPNk1W3LhscGKfx2bV8XVv+izg2zMLec5aYM/LrJg6HpJzgQJ\n"
"IKBt1tWQkxRvO7LO3znSp8A9DXotvr0MkIqcjQIDAQABAoIBAEMAaF3oW9deTvIn\n"
"/4nF54KLXEv3zGYd3QUhogt0VPGv0XQIZBwA+jGy5zUE7kKHiq9tBsU7kJycgkTx\n"
"JHn/whA4dbUaj+MIXYAWFGSoks3J3Vma6L9yXr4jlKefAcx3IesMCamwhF+odUod\n"
"iQ4HKB2vCRhAsTSgI/27isgst2TlJsGMf7ED2N1jae8ZyOITi2g0F1edRYBwgSHq\n"
"MZvccZh/IpuTOPEVxuITYyQT9WF0TCz7cK4wCP5dACQQB6Or8l2xiUf9dx3I7kwR\n"
"7wvivI+jAoxR/peOXx2o0bHPcqh41rbhbE00XOcIReGoyLsRDvicw3hgFe6UxcEm\n"
"PlpFzaECgYEAyBPpzK3x0iXj66iO6erXzciN5cXF8IZhC7xcCgGOpnjgrMV3FUNv\n"
"L0Qu8zUlTJHfWpITCZawPpbNMaNShykLU6NqxUPXGtaH/xVUZm9VbkRwBQoQKg+w\n"
"x2+hAWTGu4rWtSaWMHJuwI0SYyopvJtBgDO8PkmzDG24RQuRVBSE+ycCgYEAwFu6\n"
"QHVHvVm4ri1FCIK313uXTWoYhKDCm8ygDKT608bHzBoqOcXPT5mcr3IZmZitsg3Y\n"
"DyVvPGmmbLp8FmxXcz2c71e1Bupeq9V8HrMiSgMVPEIRuNKVC7WE/Ymuvpvfd+h/\n"
"RyDCu2wTI4GcJRhmAB+SpjPPOH0qaqV2eHZgSysCgYAO5eyy4QDwtQGTuqlpoaMQ\n"
"H67xPRjQIDF5vjzcQeFtY/LW6p1DaBIPYvRcB8kPOo13IQlp3V6iSnhdCdxLVDMT\n"
"t0dsCPErfm4CAISYXBHwdAgjV+x8NU7kittiTy69KEl0k7r7QIoerGKCH9GbybPG\n"
"6BNMUBCVDFZ8TbA0opKEYQKBgEl0/fxNjTbXA3qoWPt2B8SnMtFiWbiUN50NmHUb\n"
"r5meCIB94XAshQ2NyNMLDJGmR3Z+aOrnzcHRSresw2RAvWiJt9uCr+PTLpIKNZr3\n"
"p3mCEeLwDBp7eGV/TSkRIgUyOzVsOOatsQ+nputhPILB/XnAlN0ZXeHhkoglZcd8\n"
"1Sr/AoGAU7nlyAMQNd/tckwPTnM++0ewrFvwrfpS7f2dhcYbIhfqQ3I03Gwzjkkg\n"
"G85uzTg/8iO4oxPRjqPvc7JaoDDmGY/efQvjR+FdwDOuy+XZPImZIgGjl0yvAMFU\n"
"6azU+OxtwV+Yyfad4rGxaXZsqOIs18to94t2kjI0t8ur/4Q7C5w=\n"
"-----END RSA PRIVATE KEY-----\n"; // to verify the client
const char *test_client_cert =
"-----BEGIN CERTIFICATE-----\n"
"MIIDnjCCAoYCFBRQlTP3aMzr8YtFlYoaVtrPIN6xMA0GCSqGSIb3DQEBCwUAMIGH\n"
"MQswCQYDVQQGEwJWTjEQMA4GA1UECAwHdmlldG5hbTEQMA4GA1UEBwwHdmlldG5h\n"
"bTEOMAwGA1UECgwFcGVjb20xDTALBgNVBAsMBHRlc3QxDTALBgNVBAMMBG1xdHQx\n"
"JjAkBgkqhkiG9w0BCQEWF2NwdHByaWNlMTIzQG91dGxvb2suY29tMB4XDTIyMTEw\n"
"MzA4MTMzMVoXDTIzMDIxMTA4MTMzMVowgY4xCzAJBgNVBAYTAlZOMRAwDgYDVQQI\n"
"DAd2aWV0bmFtMRAwDgYDVQQHDAd2aWV0bmFtMQ4wDAYDVQQKDAVwZWNvbTENMAsG\n"
"A1UECwwEdGVzdDETMBEGA1UEAwwKbXF0dGNsaWVudDEnMCUGCSqGSIb3DQEJARYY\n"
"Y3B0cHJpY2VAMTIzQG91dGxvb2suY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n"
"MIIBCgKCAQEAllaf/na5h3yDr2zoYsYGGqt/d93/AAUTculGTXdGGbRwyHueb0Ba\n"
"MeX+ht9siZ82iuaZ/5mJ/kq8WVwlrkegOAvU7SQDoALPM7VLMLSMbnn2WqogWE48\n"
"TkWU0WddtTFHVDGLX8zMC1TQ1VKyVzp2QtCW9RPJNun9CVJSoZ34uM5hBL1f7MY7\n"
"t/QsDYi14UtULDsSnVz+tDLiPrBkZOPEVhopCH1gvljcDTcICfawyK5nlCKcAnUW\n"
"THEUzf89WCJkPNk1W3LhscGKfx2bV8XVv+izg2zMLec5aYM/LrJg6HpJzgQJIKBt\n"
"1tWQkxRvO7LO3znSp8A9DXotvr0MkIqcjQIDAQABMA0GCSqGSIb3DQEBCwUAA4IB\n"
"AQCF33dWLyL/QJKDBNtKc6WwmOn97u74jkIYdgRHgQwNvrmLHRgZPb6Bhzy5KAIY\n"
"qJcPA6Cn/m4utUWjAXRPj9zDT5xyeC843R22KQASjmPBnEyfDZuXmUPjjNJUSUx6\n"
"JGk/bwPQDLT2ID+vl3OInm4ypgwbGaqlhn41m0F2smanuZUFgEmN5+tJpkwK/tVP\n"
"IYHJ5HPnFqDFs84Fp12HU2QcqbOUEZ/d77Yw/dfb20cvgW2xkHKEAhz7d9EpD4ov\n"
"S5ZnelKxvqlVzI2v2I6MJkRdeP2IfYofNfRo2s7S5u+h/2SQu1MbbarS/jd32Ldz\n"
"14EVvDj+sCF2g7skdJ3kYCPI\n"
"-----END CERTIFICATE-----\n"; // to verify the client
Server config:
listen:0.0.0.0:4222
jetstream:{
max_memory_store: 1073741824
max_file_store: 1073741824
}
mqtt {
# Specify a host and port to listen for websocket connections
#
listen: "0.0.0.0:8883"
# It can also be configured with individual parameters,
# namely host and port.
#
# host: "hostname"
# port: 1883
# TLS configuration.
tls {
cert_file: /etc/tls/mqtt/broker/broker.crt
key_file: /etc/tls/mqtt/broker/broker.key
ca_file: /etc/tls/mqtt/ca/ca.crt
verify: true
timeout: 2.0
# verify_and_map: true
}
# no_auth_user: "my_username_for_apps_not_providing_credentials"
# authorization {
# # username: "my_user_name"
# # password: "my_password"
# # token: "my_token"
# # timeout: 2.0
# }
ack_wait: "1m"
max_ack_pending: 100
}
tls:{
cert_file: /etc/tls/natsio/server-cert.pem
key_file: /etc/tls/natsio/server-key.pem
ca_file: /etc/tls/natsio/ca-cert.pem
}
http_port: 8222
# system_account: AAOQAS43OSVDMF3ERYSNL3GMGZRD7GILDGDET6R52NFZKEWJOTTVNYZ4
# resolver: {
# type: full
# dir: './jwt'
# allow_delete: false
# interval: "2m"
# limit: 1000
# }
Logs from NATS server:
test-nats-dev-1 | [1] 2022/11/03 10:29:32.794114 [ERR] 192.168.1.14:57479 - mid:699 - TLS handshake error: remote error: tls: bad certificate
test-nats-dev-1 | [1] 2022/11/03 10:29:37.989099 [ERR] 192.168.1.14:57480 - mid:700 - TLS handshake error: remote error: tls: bad certificate
ESP32 logs:
Attempting MQTT connection...[2959556][E][ssl_client.cpp:37] _handle_error(): [start_ssl_client():276]: (-9984) X509 - Certificate verification failed, e.g. CRL, CA or signature check failed
[2959559][E][WiFiClientSecure.cpp:135] connect(): start_ssl_client: -9984
failed, rc=-2 try again in 5 seconds
Attempting MQTT connection...[2964762][E][ssl_client.cpp:37] _handle_error(): [start_ssl_client():276]: (-9984) X509 - Certificate verification failed, e.g. CRL, CA or signature check failed
[2964765][E][WiFiClientSecure.cpp:135] connect(): start_ssl_client: -9984
failed, rc=-2 try again in 5 seconds
Attempting MQTT connection...[2976298][E][ssl_client.cpp:37] _handle_error(): [start_ssl_client():276]: (-9984) X509 - Certificate verification failed, e.g. CRL, CA or signature check failed
[2976301][E][WiFiClientSecure.cpp:135] connect(): start_ssl_client: -9984
failed, rc=-2 try again in 5 seconds
I found the problem is my cert is using domain for certification and I using IP for connection. That is make it not working.
After change to using domain in connection it works normally.
Domain TLS: https://docs.cpanel.net/knowledge-base/general-systems-administration/what-is-domain-tls/
IP TLS: Is it possible to have SSL certificate for IP address, not domain name?

Amazon root certificate pinning in Flutter, Dart

I'm using AWS CA to generate an SSL certificate for ElasticBeanstalk that I'm using in my Flutter app.
Based on the bets practices, I'm trying to pin HTTP client the Root certificate from Amazon Trusted Services
I face 2 issues with the Flutter HTTP client:
Whenever I try to load the certificate it crashes:
[VERBOSE-2:ui_dart_state.cc(209)] Unhandled Exception: TlsException: Failure trusting builtin roots (OS Error: BAD_PKCS12_DATA(pkcs8_x509.c:657), errno = 0)
This is the certificate I use (one of five, I add them all):
final _awsRoot1 = _decodePEM("""-----BEGIN CERTIFICATE-----
MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
rqXRfboQnoZsG4q5WTP468SQvvG5
-----END CERTIFICATE-----""");
And this is what I do to decode PEM :
Uint8List _decodePEM(pem) {
for (var s in _startsWith) {
if (pem.startsWith(s)) pem = pem.substring(s.length);
}
for (var s in _endsWith) {
if (pem.endsWith(s)) pem = pem.substring(0, pem.length - s.length);
}
pem = pem.replaceAll('\n', '');
pem = pem.replaceAll('\r', '');
return Uint8List.fromList(base64.decode(pem));
}
And add it via:
void certificatePinningPem(SecurityContext context) {
context.setTrustedCertificatesBytes(_awsRoot1);
context.setTrustedCertificatesBytes(_awsRoot2);
context.setTrustedCertificatesBytes(_awsRoot3);
context.setTrustedCertificatesBytes(_awsRoot4);
context.setTrustedCertificatesBytes(_awsRoot5);
}
I get the same exception when I read DER file :
final aws1 = await rootBundle.load('assets/cer/aws1.cer');
context.setTrustedCertificatesBytes(aws1.buffer.asUint8List());
PEM file from the connection is different
Despite that, when I use badCertificateCallback, pem file from the certificate doesn't match any of those five from repo So how to get Root certificate from connection?
httpClient.badCertificateCallback = (
X509Certificate certificate,
String host,
int port,
) {
print('Bad certificate: ${certificate.pem} for host $host:$port');
return false;
};
Any suggestion on how to properly do certificate pinning in Flutter with AWS Root certificates?
I found a few related threads but they don't really help, i.e. https://github.com/flutter/flutter/issues/39190#issuecomment-693315205

Cannot send SMTP email from JBoss java app in Amazon EC2 instance: Could not convert socket to TLS

I'm running a java app in JBoss 6.4.0 in an Amazon Web Services red hat 8 EC2 instance.
When my app tries to send an email via javax.mail I'm getting an error "Could not convert socket to TLS".
I then coded up the AmazonSESSample.java sample program and tried it. I ran it in my EC2 instance outside JBoss and it ran successfully. (The AmazonSESSample program can be found here: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/examples-send-using-smtp.html)
Then I commented out the email code in my java app, and replaced it with the code in AmazonSESSample.java. When I run my java app with the AmazonSESSample code in JBoss I get the same error: "Could not convert socket to TLS". So the AmazonSESSample works fine outside JBoss, and gives an error when running inside JBoss.
Here is the AmazonSESSample code in my app. Can somebody help me fix the "Could not convert socket to TLS" error?:
public class AmazonSESSample {
private static final Logger logger = LogManager.getFormatterLogger("AmazonSESSample");
// Replace sender#example.com with your "From" address.
// This address must be verified.
static final String FROM = "email1#gmail.com";
static final String FROMNAME = "Steve";
// Replace recipient#example.com with a "To" address. If your account
// is still in the sandbox, this address must be verified.
static final String TO = "email2#gmail.com";
// Replace smtp_username with your Amazon SES SMTP user name.
static final String SMTP_USERNAME = "thisIsNotActualghijikl";
// Replace smtp_password with your Amazon SES SMTP password.
static final String SMTP_PASSWORD = "abcdefThisIsNotActual";
// Amazon SES SMTP host name. This example uses the US West (Oregon) region.
// See https://docs.aws.amazon.com/ses/latest/DeveloperGuide/regions.html#region-endpoints
// for more information.
static final String HOST = "email-smtp.us-east-2.amazonaws.com";
// The port you will connect to on the Amazon SES SMTP endpoint.
static final int PORT = 587;
static final String SUBJECT = "Amazon SES test (SMTP interface accessed using Java)";
static final String BODY = String.join(
System.getProperty("line.separator"),
"<h1>Amazon SES SMTP Email Test</h1>",
"<p>This email was sent with Amazon SES using the ",
"<a href='https://github.com/javaee/javamail'>Javamail Package</a>",
" for <a href='https://www.java.com'>Java</a>."
);
public int sendEmail(DisplayEmailMessage emailMessage) throws UnsupportedEncodingException, MessagingException {
// Create a Properties object to contain connection configuration information.
Properties props = System.getProperties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.port", PORT);
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.auth", "true");
// Create a Session object to represent a mail session with the specified properties.
Session session = Session.getDefaultInstance(props);
// Create a message with the specified information.
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(FROM, FROMNAME));
msg.setRecipient(Message.RecipientType.TO, new InternetAddress(TO));
msg.setSubject(SUBJECT);
msg.setContent(BODY, "text/html");
// Create a transport.
Transport transport = session.getTransport();
// Send the message.
try {
System.out.println("Sending...");
// Connect to Amazon SES using the SMTP username and password you specified above.
transport.connect(HOST, SMTP_USERNAME, SMTP_PASSWORD);
// Send the email.
transport.sendMessage(msg, msg.getAllRecipients());
System.out.println("Email sent!");
}
catch (Exception ex) {
System.out.println("The email was not sent.");
System.out.println("Error message: " + ex.getMessage());
}
finally {
// Close and terminate the connection.
transport.close();
}
return 0;
}
}
Here is the javamail debug output:
DEBUG: setDebug: JavaMail version 1.4.5.redhat-2
Sending email to 123#gmail.com
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc]
Starting to connect at Sun Dec 26 13:14:23 UTC 2021 to email 123#gmail.com
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "smtp.dreamhost.com", port 587, isSSL false
220 pdx1-sub0-mail-a290.dreamhost.com ESMTP
DEBUG SMTP: connected to host "smtp.dreamhost.com", port: 587
EHLO ip-172-31-29-30.us-east-2.compute.internal
250-pdx1-sub0-mail-a290.dreamhost.com
250-PIPELINING
250-SIZE 40960000
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 CHUNKING
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "SIZE", arg "40960000"
DEBUG SMTP: Found extension "ETRN", arg ""
DEBUG SMTP: Found extension "STARTTLS", arg ""
DEBUG SMTP: Found extension "AUTH", arg "PLAIN LOGIN"
DEBUG SMTP: Found extension "AUTH=PLAIN", arg "LOGIN"
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
STARTTLS
220 2.0.0 Ready to start TLS
MessagingException
javax.mail.MessagingException: Could not convert socket to TLS
I fixed this by upgrading my JBoss to 7.4.0.

APNS issue with django

I'm using the following project for enabling APNS in my project:
https://github.com/stephenmuss/django-ios-notifications
I'm able to send and receive push notifications on my production app fine, but the sandbox apns is having strange issues which i'm not able to solve. It's constantly not connecting to the push service. When I do manually the _connect() on the APNService or FeedbackService classes, I get the following error:
File "/Users/MyUser/git/prod/django/ios_notifications/models.py", line 56, in _connect
self.connection.do_handshake()
Error: [('SSL routines', 'SSL3_READ_BYTES', 'sslv3 alert handshake failure')]
I tried recreating the APN certificate a number of times and constantly get the same error. Is there anything else i'm missing?
I'm using the endpoints gateway.push.apple.com and gateway.sandbox.push.apple.com for connecting to the service. Is there anything else I should look into for this? I have read the following:
Apns php error "Failed to connect to APNS: 110 Connection timed out."
Converting PKCS#12 certificate into PEM using OpenSSL
Error Using PHP for iPhone APNS
Turns out Apple changed ssl context from SSL3 to TLSv1 in development. They will do this in Production eventually (not sure when). The following link shows my pull request which was accepted into the above project:
https://github.com/stephenmuss/django-ios-notifications/commit/879d589c032b935ab2921b099fd3286440bc174e
Basically, use OpenSSL.SSL.TLSv1_METHOD if you're using python or something similar in other languages.
Although OpenSSL.SSL.SSLv3_METHOD works in production, it may not work in the near future. OpenSSL.SSL.TLSv1_METHOD works in production and development.
UPDATE
Apple will remove SSL 3.0 support in production on October 29th, 2014 due to the poodle flaw.
https://developer.apple.com/news/?id=10222014a
I have worked on APN using python-django, for this you need three things URL, PORT and Certificate provided by Apple for authentication.
views.py
import socket, ssl, json, struct
theCertfile = '/tmp/abc.cert' ## absolute path where certificate file is placed.
ios_url = 'gateway.push.apple.com'
ios_port = 2195
deviceToken = '3234t54tgwg34g' ## ios device token to which you want to send notification
def ios_push(msg, theCertfile, ios_url, ios_port, deviceToken):
thePayLoad = {
'aps': {
'alert':msg,
'sound':'default',
'badge':0,
},
}
theHost = ( ios_url, ios_port )
data = json.dumps( thePayLoad )
deviceToken = deviceToken.replace(' ','')
byteToken = deviceToken.decode('hex') # Python 2
theFormat = '!BH32sH%ds' % len(data)
theNotification = struct.pack( theFormat, 0, 32, byteToken, len(data), data )
# Create our connection using the certfile saved locally
ssl_sock = ssl.wrap_socket( socket.socket( socket.AF_INET, socket.SOCK_STREAM ), certfile = theCertfile )
ssl_sock.connect( theHost )
# Write out our data
ssl_sock.write( theNotification )
# Close the connection -- apple would prefer that we keep
# a connection open and push data as needed.
ssl_sock.close()
Hopefully this would work for you.