Configure Matomo to send emails using AWS Signature Version 4 - matomo

My Matomo instances have been logging messages like this for a while:
2022-08-31 06:57:46 SERVER -> CLIENT: 535 Signature Version 2 is deprecated for use with SES from March 26, 2021. From that date on, we are progressively rejecting such requests. To resolve the issue, you must migrate to Signature Version 4. If you created your SMTP credentials in the SES Console, please create new credentials and replace the former ones. If you are deriving Signature Version 2 credentials from a IAM user, please start using the Signature Version 4 algorithm: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-credentia
2022-08-31 06:57:46 SMTP ERROR: User & Password command failed: 535 Signature Version 2 is deprecated for use with SES from March 26, 2021. From that date on, we are progressively rejecting such requests. To resolve the issue, you must migrate to Signature Version 4. If you created your SMTP credentials in the SES Console, please create new credentials and replace the former ones. If you are deriving Signature Version 2 credentials from a IAM user, please start using the Signature Version 4 algorithm: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-credentia
2022-08-31 06:57:46 SMTP Error: Could not authenticate.
So I created a new SMTP user that should have the new signature automatically (At least I hope so). Then I got 3 values from AWS:
IAM User Name
Smtp Username
Smtp Password
Now I am wondering, why the connection does not work at all anymore. My config.ini.php now looks like this:
[mail]
transport = "smtp"
port = 25
host = "email-smtp.eu-west-1.amazonaws.com"
type = "Login"
encryption = "tls"
username = "[[Smtp Username]]"
password = "[[Smtp Password]]"
Do I need to use a different type or encryption, so the mails are sent again?
Currently the error message says:
Uncaught exception: /var/www/html/vendor/phpmailer/phpmailer/src/PHPMailer.php(2178): SMTP Error: Could not authenticate. [Query: , CLI mode: 1]

Have you tried different ports?
Check this part of Amazon documentation: https://docs.aws.amazon.com/ses/latest/dg/send-email-smtp-software-package.html
I had a problem with setting up a connection with different tools (Grafana and Sendgrid) and I had to skip the certificate verification process (ref. https://piotr.gg/dev-ops/setup-grafana-email-notification-via-sendgrid-smtp-also-for-bitnami-grafana.html)

Related

Identity Server 4 Failed to Validate the Token from localhost for the protected API

Scenario
localhost & 192.168.0.10 refer to the same machine called MyPC
Identity server is running on that "MyPC"
UI uses "localhost" to communicate with Identity Server
The protected API uses "192.168.0.10" to communicate with Identity Server
UI & API talk to each other and authenticated by an Identity Server
In the above scenario, If I use Identity Server 3, everything is fine; however the problem started when I switch to Identity Server 4 (the latest version). I got this error in the API
System.IdentityModel.Tokens.SecurityTokenInvalidIssuerException: IDX10205: Issuer validation failed. Issuer: 'localhost:9987'......
That error will go away if I use the same IP address (localhost or 192.168.0.10) for both UI & API to communicate with the Identity Server.
Could anyone point me to the direction to fix this? I do need the ability to access Identity Server using either 127.0.0.1, localhost, Lan Addresses, Wan Addresses?
This is code that I am using in the API Startup:
services.AddAuthentication(o =>
{
o.DefaultScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
o.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
})
.AddIdentityServerAuthentication(x =>
{
x.Authority = Configuration.GetSection("URL").GetSection("IdentityServerURL").Value;
x.ApiSecret = Configuration.GetSection("Resource").GetSection("APISecrets").Value;
x.ApiName = Configuration.GetSection("Resource").GetSection("APIName").Value;
x.SupportedTokens = SupportedTokens.Both;
x.RequireHttpsMetadata = false;
});
P/S: I had done research on this but there wasn't any clear answer on this.
The IdentityServer4 server will include an "Issuer" in the JWT token. You can double check e.g. using jwt.io what that is. From the relevant docs:
Set the issuer name that will appear in the discovery document and the issued JWT tokens. It is recommended to not set this property, which infers the issuer name from the host name that is used by the clients.
If you do custom naming, aliasing, ports, subdomains, and whatnot, then you could go ahead and set it manually anyways (both on the server side and on the validation side), or set issuer validation off (perhaps only in dev) altogether.

How does NTLM SSO in a Windows Domain works?

I made a proof of concept for single-sign-on in TypeScript using NodeSSPI. This works, I get the username where I'm logged in on our corporate AD domain - without entering any account information or credentials. But I want to know how this is possible in detail, cause it works in IE and Chrome out of the box. I found this MSDN article about NTLM which says:
Username of the logged in user is send to the server
Server generated random number challenge and send it to the client
Client encrypts the challenge with the user password hash and send it back to server
Server sends username, challenge and challenge-response to DC
DC compares the PW with the database and authenticates the user if it matches
I'm especially wonder about step 1 and 2: Where does this happen? How is e.g. the username transfered to the server? Is it part of the http request? I took a look in the request from the chrome developer tools and couldn't see any header or other information which indicates that e.g. my AD username is send to the server.
Please note: These questions only apply to SSO where no credentials are supplied by the user! Cause when the user enters his credentials this is clear.
Is it part of the http request?
Yes. As described in RFC 4559, you should see the WWW-Authenticate: Negotiate header from the server's response, and as a consequence the Authorization header from the client.
If the developers tools don't show this, please come back with a network capture.

ADFS vNext Client Authentication (WPF) (Windows Server 2016 Preview 3)

I have a Windows Server 2016 TechnicalPreview 3 with a configured ADFS vNext, as first client I have created an MVC Application as a ReplingPartyTrust.
The authentication with the ADFS work really well with the MVC Application.
Now to the problem: I have written a Native Application (WPF) which i want to authenticate against the ADFS.
The Steps i did are:
To inform the ADFS of my new WPF Client i ran the the following PowerShell Script:
Add-ADFSClient -ClientType Public -Name “MyClient” -ClientId “E1CF1107-FF90-4228-93BF-26052DD2C714” -RedirectUri “https://E1CF1107-FF90-4228-93BF-26052DD2C714/redir´”
To authenticate the client (Code-Wise) i used the following NuGet-Package:
Microsoft.IdentityModel.Clients.ActiveDirectory (3.5 (Alpha))
Then I wrote the following code:
string authority = "https://win2016preview.server.local/adfs/ls";
string resourceURI = "https://adfs.server.local/MyMVCApp";
string clientReturnURI = "https://e1cf1107-ff90-4228-93bf-26052dd2c714/redir";
string clientID = "E1CF1107-FF90-4228-93BF-26052DD2C714";
var ac = new AuthenticationContext(authority, false);
var ar = await ac.AcquireTokenAsync(resourceURI, clientID, new
Uri(clientReturnURI),
new PlatformParameters(PromptBehavior.Auto, new
WindowInteropHelper(this).Handle));
With this code, the client should authenticate at the ADFS (over OAuth i think) and prompt the user to enter his organisation credentials.
If i run the application this window appears:
I choose Yes (Ja) and the credential prompt opens. In the same time the following exception occures
In the event log if the server ADFS the following error message appears:
Microsoft.IdentityServer.Web.Protocols.OAuth.Exceptions.OAuthAuthorizationUnauthorizedClientException: MSIS9321: Received invalid OAuth request. The client 'E1CF1107-FF90-4228-93BF-26052DD2C714' is forbidden to access the resource 'https://adfs.server.local/MyMVCApp.
at Microsoft.IdentityServer.Web.Protocols.OAuth.OAuthAuthorization.OAuthAuthorizationRequestContext.ValidateCore()
at Microsoft.IdentityServer.Web.Protocols.ProtocolContext.Validate()
at Microsoft.IdentityServer.Web.Protocols.OAuth.OAuthAuthorization.OAuthAuthorizationProtocolHandler.GetRequiredPipelineBehaviors(ProtocolContext pContext)
at Microsoft.IdentityServer.Web.PassiveProtocolListener.GatherDeviceSecurityToken(ProtocolContext protocolContext, PassiveProtocolHandler protocolHandler)
at Microsoft.IdentityServer.Web.PassiveProtocolListener.OnGetContext(WrappedHttpListenerContext context)
As far as i can tell, the ADFS recognizes the Client Id and tries to authenticate it. But the ADFS rejects the Client.
Did i forget to configure something? The client should just prompt the user, which authenticates against the ADFS, so the client can habe the AuthenticationToken.
I hope you can follow me. Thank you in advance!
The solution is very simple :)
Add the property IssuanceAuthorizationRules (Add-ADFSRelyingPartyTrust )
-IssuanceAuthorizationRules '=> issue (Type = "http://schemas.microsoft.com/authorization/claims/permit" value = "true");'

CXF WS-Trust service certificate configuration

Objective: Get information (using Apache CXF) from a third party (thus no control or access to the service backend) web service
which use WS-Trust i.e. it authenticates the user using a Secure Token Service in this case with UsernameToken authentication.
I have spent a LONG time trying to learn about the WS-* security standards and at the same time trying out different frameworks and
tools (Axis, Apache CXF, METRO with NetBeans, Microsoft .net, SoapUI plugin for Eclipse etc.) to connect to a specific service in
the cloud. I am trying to develop a backend client that fetch information from the service. Apache CXF is attractive here
because it seems to be the only Java framework which does not assume that everyone connecting to web services use clients deployed on a web application server.
The service providers have provided the necessary certificates and user credentials to connect to the service using STS.
They have also provided a detailed user guide using NetBeans and METRO to create a web application that is deployed on a GlassFish server.
I have followed this guide and managed to get data from the web service. Conclusion so far: The certificates are valid.
There are three certificates stored in a keystore (including chains):
webservice-encryption-certificate.cer (keystore alias: webservice-encryption)
token-signing-certificate.cer (keystore alias:
token-signing)
token-encryption-certificate.cer (keystore alias: token-encryption)
=================================================================
NetBeans configuration:
Service client:
Keystore -> token-signing-certificate.cer
Truststore -> webservice-encryption-certificate.cer
STS client:
Truststore -> token-encryption-certificate.cer
Username -> user
Password -> xxx
=================================================================
THE BIG QUESTION: How can I make a similar configuration in CXF as in NetBeans?
I'm using CXF version: 3.0.2
"Translating" this to CXF gives me the follownig exception:
WARNING: Interceptor for {http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice}SecurityTokenService#{http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice}Trust13IssueAsync has thrown exception, unwinding now
org.apache.cxf.binding.soap.SoapFault: The signature or decryption was invalid
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.createSoapFault(WSS4JInInterceptor.java:841)
Here is what i tried in CXF (amongst MANY other things):
MyService service = new MyService(); // Stub created from WSDL (real service name has been renamed to MyService)
MyServiceInterface port = service.getPort();
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(port);
Bus bus = ((EndpointImpl) client.getEndpoint()).getBus();
STSClient stsClient = new STSClient(bus);
stsClient.setWsdlLocation("https://login.some-domain.com/adfs/services/trust/mex"); // Web service is using ADFS 2.0 with MEX
stsClient.setServiceQName(new QName("http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice", "SecurityTokenService"));
stsClient.setEndpointQName(new QName("http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice", "UserNameWSTrustBinding_IWSTrust13Async"));
stsClient.setSendRenewing(false);
stsClient.getRequestContext().put("ws-security.sts.token.properties", "clientTruststore.properties");
stsClient.getRequestContext().put("ws-security.sts.token.username", "webservice-encryption"); // MOST LIKELY WRONG - WHERE DO I PUT THIS CERTIFICATE?
Map<String, Object> ctx = ((BindingProvider) port).getRequestContext();
ctx.put("ws-security.sts.prefer-wsmex", true); // If set to false some policies will not be satisfied
ctx.put("ws-security.username", "user"); // REQUIRED OR FAIL WITH: No username available
ctx.put("ws-security.password", "xxx"); // REQUIRED OR FAIL: No username available
ctx.put("ws-security.encryption.properties", "clientTruststore.properties"); // REQUIRED OR FAIL WITH: A encryption username needs to be declared
ctx.put("ws-security.encryption.username", "token-encryption"); // REQUIRED OR FAIL WITH: A encryption username needs to be declared
ctx.put("ws-security.signature.properties", "clientTruststore.properties");
ctx.put("ws-security.signature.username", "token-signing");
ctx.put("ws-security.is-bsp-compliant", "false");
ctx.put("ws-security.sts.client", stsClient);
port.callSomething(createMyRequestObject());
I have tried to "decrypt" the meaning of the properties used in the code snippet above based on the following link (along many other tutorials and articles on the subject) to make sense in relation to WS-Trust and the certificates at hand.
http://cxf.apache.org/javadoc/latest/org/apache/cxf/ws/security/SecurityConstants.html
I have tried all sorts of combinations using the constants but with no success.
How do I "pass" the service certificate (webservice-encryption) to the STS to tell it "this is the service that I want to use"?
By the way I have captured the traffic with Fiddler, and the request looks perfectly right compared to traffic captured with the NetBeans solution i.e. it contains timestamp, encrypted sections etc.
I KEEP GETTING "The signature or decryption was invalid"
Can anyone help please?
What does the response method from the STS look like? Is it an error message or does it look like the call succeeded? If it is an error message then it looks like you may be using the wrong certificates...you will need to enable logging on the service to figure out what the exact error is. If the call succeeded, then enable DEBUG logging on the client side and see what the problem is.
Colm.
We had a similar problem. Perhaps you must add JCE Unlimited Strength Policy jar files to JDK?

Why does Silverlight 4 ClientHttp WebRequest prompt the user for a login and password?

One of the new features of the client http stack in Silverlight 4 is the ability to supply network credentials. When I use this feature Windows shows a "Windows Security" message box that prompts the user for a login and password (text in the box is "The server xx at xx requires a username and password. Warning: This server is requesting that your username and password be sent in an insecure manner (basic authentication without a secure connection)."). I'm setting the login and password as shown below so I'm not sure why this is displayed. My code is:
var request = WebRequestCreator.ClientHttp.Create(new Uri("http://myserver:8080/gui/?list=1"));
request.Credentials = new NetworkCredential("login", "password");
request.BeginGetResponse(new AsyncCallback(OnRequestComplete), request);
If I enter the username and password into the messagebox the request completes successfully. For a number of reasons I'd rather prompt the user for the login and password so I'd like to avoid the messagebox if possible.
My setup is Silverlight 4 final, VS 2010 final, Windows 7 x86. The application is out of browser with elevated permissions.
If you call to the web server is a cross-site call you will have to specify a client access policy on the web server to enable the authorization header. You should either place the XAP file on http://myserver:8080 or add a clientaccesspolicy.xml file to the web site on http://myserver:8080.
Tim Heuer has some more information about how Silverlight 4 enables Authorization header modification.
The warning about 'requesting that your username and password be sent in an insecure manner' likely means that you are not sending the data over ssl (https) which would be by webbrowser standards, a secure connection.
You can't get past this because this prompt is showed or not showed depending on the users internet security settings. The only way you can fix it from your end is by using ssl.

Resources