Connect to windows live messenger xmpp with php - xmpp

How can i connect xmpp windows live messenger with php? I am using xmpphp and jaxl library and I connected with google talk sucsessfully.

Jaxl library comes with inbuilt support for PLAIN, google talk X-OAUTH2, DIGEST-MD5, CRAM-MD5, SCRAM-SHA-1, EXTERNAL and facebook X-FACEBOOK-PLATFORM authentication mechanisms.
It does also provide ability to implement any custom authentication mechanism that you might need inside your application. Implementing X-MESSENGER-OAUTH2 authentication should be easy as described below:
Checkout latest version of JAXL library and initialize your JAXL client object as follows:
require_once 'jaxl.php';
$client = new JAXL(array(
'jid' => 'messenger.live.com', // <-- dummy jid required for DNS SRV lookup
'pass' => '',
'log_level' => JAXL_DEBUG
));
Register callback for on_stream_features event as shown below and send auth packet as described in msdn documentation:
$client->add_cb('on_stream_features', function($stanza) {
global $client, $access_token;
$auth = new JAXLXml('auth', NS_SASL, array('mechanism'=>'X-MESSENGER-OAUTH2'));
$auth->t($access_token);
$client->send($auth);
return 'wait_for_sasl_response';
});
This should get you going.
Note: Currently version of Jaxl library rely on input jabber id for DNS SRV lookup, from where it extracts target host:port for establishing socket connection. Hence you will have to pass dummy values for jid and pass as shown above (until this gets fixed in future versions).
I have written above steps without any testing, but it should work fine. More details on how to work with JAXLXml style of XML creation can be found here.

Related

Using TidIMAP4 component to retrieve email, need to switch to using Modern Authentication

I have a program that I wrote that monitors a mail box and retrieves messages and puts contents in a database. My email administrators have notified me that my application is using Basic Authentication and that Microsoft will drop support for that starting in October 2022. They tell me I need to use Modern Authentication. Does the Indy component TidIMAP4 support that? The links to documentation on the website seem to all be broken: https://www.indyproject.org/documentation/
Here is my current connection code, using the default AuthType of iatUserPass. Is that what I need to change? Is iatSASL modern authentication and how would I use that? Just switching the property no longer worked to connect. I probably have to change other properties to work with that.
procedure TdmMAARCEmails.InitializeIMAPConnection;
begin
IMAPClient := TIdIMAP4.Create(self);
try
// IMAPClient.AuthType := iatSASL;
OpenSSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(self);
OpenSSLHandler.sslOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
IMAPClient.IOHandler := OpenSSLHandler;
// IMAPClient.Host := 'imap.gmail.com';
IMAPClient.Host := FIniFile.ReadString('EMAIL', 'IMAPI_SERVER', '');
IMAPClient.Port := FIniFile.ReadInteger('EMAIL', 'IMAPI_PORT', 993);
IMAPClient.UseTLS := utUseImplicitTLS;
IMAPClient.Username := self.UserName;
IMAPClient.Password := self.Password;
IMAPClient.Connect;
except
on E:Exception do
writeln(E.Message);
end;
end;
Does the Indy component TidIMAP4 support that?
Indy does not officially support "Modern Authentication" (aka OAuth 2.0) at this time (open ticket #192).
Unofficially, there is currently a sasl-oauth branch in Indy's GitHub repo that is beginning to add in this support. If you were to try using this branch, you would be responsible for obtaining the necessary OAuth access token from Microsoft (see Authenticate an IMAP, POP or SMTP connection using OAuth - sections "Register your application" and "Get an access token"), and then you could assign that token to the TIdIMAP4 component to authenticate its IMAP connections (the "Authenticate connection requests" section of that document).
Alternatively, there is a 3rd party OAuth 2 implementation for Indy at this repo. It is meant for Gmail SMTP, but should be usable/adaptable for IMAP, too.
The links to documentation on the website seem to all be broken
Known issue: Links to old Indy website pages are currently broken
using the default AuthType of iatUserPass. Is that what I need to change?
Yes. iatUserPass uses the IMAP LOGIN <username> <password> command, which is what is being deprecated. iatSASL uses the IMAP AUTHENTICATE <mechanism> <parameters> command instead. Per the document above, Microsoft is expecting an AUTHENTICATE XOAUTH2 ... command.
Is iatSASL modern authentication and how would I use that?
Setting the AuthType to iatSASL is just the first step towards enabling "modern authentication". You would then need to fill out the TIdIMAP4.SASLMechanisms property with references to any TIdSASL-derived components you need, which will handle the actual authentications.
Indy has several TIdSASL... classes for various authentications (CRAM-MD5, CRAM-SHA1, NTLM, Digest, etc), but none for OAuth 2 yet. The sasl-oauth branch is adding a few new TIdSASL... classes, including TIdSASLXOAuth2 which would cover this situation (the other repo has a TIdSASLXOAuth class for this same task).
Or, you can just write your own TIdSASL-derived class to handle authentication however you need. For instance, if you just want to copy the TIdSASLXOAuth2/TIdSASLXOAuth implementation into your own code locally.
Just switching the property no longer worked to connect.
Correct, because your authentication setup is incomplete. See above.

Problem accessing Google API protected with OAuth2 by using LWP::Authen::OAuth2

I am currently coding a service on a perl server, that shall send a request to the Firebase Cloud Messaging API, which will then send push notifications to an app instance.
Since FCM is part of the Google API family, an OAuth2 token is required to access the API. During my research I found this perl solution. Because my service is running on an non-Google server environment, I can't use Google Application Default Credentials, but have to provide them manually, so I downloaded a json containing a private key following this description.
Reading the documentation of LWP::Authen::OAuth2 I got a little confused, where to put which parameter from the json into the $oauth2 object, because often different names are used to reference to the same values, like I suspect.
The json related to my firebase project:
{
"type": "service_account",
"project_id": "my_project_id",
"private_key_id": "some_key_id",
"private_key": "-----BEGIN PRIVATE KEY-----very_long_key-----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-o8sf4#<my_project_id>.iam.gserviceaccount.com",
"client_id": "some_client_id",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-o8sf4%40<my_project_id>.iam.gserviceaccount.com"
}
The implementation of the $oauth object looks like this:
my $oauth2 = LWP::Authen::OAuth2->new(
client_id => "Public from service provider",
#probably that will be "some_client_id" from above
client_secret => "s3cr3t fr0m svc prov",
#the "very_long_key"?
service_provider => "Google",
#the "auth_uri"? That's what I would suggest here
#I've read some about the LWP::Authen::OAuth2::ServiceProvider module
#do I have to create an instance of that here?
#if so, which params do I need for that from the json?
redirect_uri => "https://your.url.com/",
#the FCM api I want to call?
# Optional hook, but recommended.
save_tokens => \&save_tokens,
save_tokens_args => [ $dbh ],
# This is for when you have tokens from last time.
token_string => $token_string.
#yes, i copy-pasted that from the docs
);
Now, as a beginner in Perl and a disliker of ambiguous key-values names, i'm a little confused, which value to put where and would be glad if anyone could help me with a guide here, what to put where even if this seems like very rookie question, it is important for me :D. So i'm thankful for every helpful answer!
EDIT
When trying to generate a JSON Web Token manually in my perl service using Crypt::JWT, i came across another trip wire, which made me doubt that the according authentication API from Google "https://www.googleapis.com/auth/firebase.messaging" still accepts Bearer tokens ... I tried the generate my JWT, which seemed to be successful, but the request I sent to the actual FCM API then gave me this:
Request had invalid authentication credentials.
Expected OAuth 2 access token, login cookie
or other valid authentication credential
In the response printed as String I then found this little guy, which confused me a lot:
Client-Warning: Unsupported authentication scheme 'bearer'
Now I'm very unsure, it bearer tokens are still supported for the FCM API, even they are used in an example on the referring docs page. Does anyone have any up-to-date information about that? Thank you very much!
Digging deeper in various documentations and testing some things I realized, that LWP::Authen::OAuth2 is not only a bit of overhead, for creating a very tiny HTTPS request to an OAuth2 protected API, it is currently not possible either.
The caveat is hidden in the service_provider, who hosts the authentication API, that I have to call to authenticate and authorize my service for accessing the actual Firecase Cloud Messaging API. In my case, this is Google, more precisely https://www.googleapis.com/auth/firebase.messaging, also referred to as scope in code.
Now one service provider can provide different authentication APIs for different clients. That's why some service providers require an additional parameter - the client_type or type respectively (for unambiguity I will use client_type) - that also affects the authentication and authorization process via OAuth2.
When creating a new $oauth2-object, and assigning a value to the field service_provider an object of module LWP::Authen::OAuth2::ServiceProvider gets created, that may need also its parameters, like the scope, to define, for which API family you want to be authorized and depending on that a client_type.
Now Google is not a no-name Service Provider, so there already is a prebuild ServiceProvider module, explicitily for Google APIs : LWP::Authen::OAuth2::ServiceProvider::Google. This automatically fills in some parameters of a ServiceProvider object, and holds a hash of available client_types to make sure you use one of them, because depending on the client_type a specific sub-module of ServiceProvider::Google gets created internally.
So I tried to test that like so:
my $oauth2 = LWP::Authen::OAuth2->new(
service_provider => "Google",
scope => "https://www.googleapis.com/auth/firebase.messaging",
client_type => "service_account", #referring to 'type' in the json
client_id => "Public from service provider",
client_secret => "s3cr3t fr0m svc prov",
redirect_uri => "this-server.mydomain.com"
);
Follwing the further description here and sending a request with the built-in LWP::UserAgent object I still got an 401 error UNAUTHENTICATED which confused me a lot. So when I read the documentation the I-don't-know-what time I stepped across this tiny line in the client_types chapter of ServiceProvider::Google:
Service Account
This client_type is for applications that login to the developer's account using the developer's credentials. See https://developers.google.com/accounts/docs/OAuth2ServiceAccount for Google's documentation.
This is not yet supported, and would require the use of JSON Web Tokens to support.
Yep, that kinda knocks out the usage of the whole LWP:Authen::OAuth family to access Firebase APIs, as almost all of them have the client_type => "service_account". Now I have a deadline for my project and can't wait for the module to get extended or extending it myself would exceed my perl skills.
But between tears of desperation there is always a glimpse of hope, as I found this Google docs page with a live-saving addendum, that it's possible to use a JSON Web Token as a Bearer token. Researching for that I found more than one Perl solution to generate JWT from JSONs like a service account, and also this very helpful Stackoverflow answer that showed me the way out of the choke point.

Send mail with Nuxt trough Sendgrid

I have a simple vuetify contact form and I want to send this forms by email.
I have tried to use a method to send the email, but it does not work, because its on client side. So I get CORS issues.
Here's my code:
async send() {
if (this.$refs.form.validate()) {
try {
const sgMail = require("#sendgrid/mail");
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
const msg = {
to: "test#example.com",
from: "me#mydomain.com",
subject: "Sending with SendGrid is Fun",
text: "and easy to do anywhere, even with Node.js",
html: "<strong>and easy to do anywhere, even with Node.js</strong>"
};
sgMail.send(msg);
}
}
}
Is Express (or an other backend) required? Is there a way to make it work using a middleware?
EDIT
Apparently, it's just not possible: https://github.com/sendgrid/sendgrid-nodejs/issues/730
The CORS policy from Sendgrid does not allow you to use their API from the browser (The 'Access-Control-Allow-Origin' header has a value 'https://sendgrid.api-docs.io').
Quoted from https://sendgrid.com/docs/for-developers/sending-email/cors/ :
In SendGrid's case, we do not allow our customers to make a browser-based call to our v3/mail/send endpoint. (...)
You can create a server-based application, which will protect your API keys from being released to the world. Languages like NodeJS, PHP, Ruby, Python, C#, Go, and Java, and others can be implemented to make calls to the API from the security of a locked down server environment.
You have to send the email from a server, which is a good thing since your API Key would be exposed by the browser otherwise.
If you are using Nuxt in SSR mode (with Node running), I guess you could create a "Server Middleware" ( https://nuxtjs.org/api/configuration-servermiddleware ), for example with a path like "/api/mail", that will send the email.
If you are using nuxt-generate to create a static site, you can use a "function as a service", with something like "https://webtask.io/", to create a small node script; that you can trigger by url from your client to send the email.

buji-pac4j integartion with Apache Shiro and identityServer3

I am trying to learn integration of buji-pac4j. I already tried demo version which is provided on following URL https://github.com/pac4j/buji-pac4j-demo but it is seem to be working for me partially. (there is some issue from ops side to give me correct call back url).
So far I can notice handshake is happening using demo code.
I’m now trying other way as it is been provided in the documentation that is client.
As per documentation:
A Client represents an authentication mechanism. It performs the login process and returns (if successful) a user profile.
My class has now following details
OidcConfiguration oidcConfiguration = new OidcConfiguration();
oidcConfiguration.setClientId("someClientIDString");
oidcConfiguration.setSecret("someClientSecretString");
oidcConfiguration.setDiscoveryURI("https://development.domainName.com/projectName/idp/.well-known/openid-configuration");
oidcConfiguration.setScope("openid email hrauser hrainfo");
oidcConfiguration.setCallbackUrl("http://localhost:8080/callback");
OidcClient oidcClient = new OidcClient(oidcConfiguration);
Config config = new Config(oidcClient);
config.addAuthorizer("admin", new RequireAnyRoleAuthorizer("ROLE_ADMIN"));
OidcAuthenticator OidcAuthenticator = new OidcAuthenticator(oidcConfiguration);
Above is mostly setting variable in the class,
What am not able to figure is out how above will actually go and talk to openID server.
What all part I am missing.
I am going through the documentation provided on https://github.com/bujiio/buji-pac4j but it is not clear to me on the flow.
Any kind of help or direction will be appreciated.
PS: I am quite new in this area so request to bear with me.

get customfield value for jira issue using JIRA SOAP API

I want to get the values of all custom fields for a particular JIRA issue using SOAP API. I have a custom field named 'Phase' having value Decision Pending for a JIRA issue JIRA-123.
I am using JIRA 5.1.3.
I am able to get all the properties of JIRA issue using SOAP API except the value of the custom field for above issue.
I tried following code, but I am not able to use ComponentManager in my code
IssueManager issueManager = ComponentManager.getInstance().getIssueManager();
CustomFieldManager customFieldManager = ComponentManager.getInstance().getCustomFieldManager();
Issue issue = issueManager.getIssueObject("JIRA-123");
CustomField customField = customFieldManager.getCustomFieldObjectByName("Phase");
Object customFieldValue = issue.getCustomFieldValue(customField);
I would highly appreciate if anyone can provide correct approach.
The SOAP API is deprecated by 5.1.3. I suggest you use the REST API - it is both more easy to use and implement.
What is REST?: read here. The basic idea is to bind HTTP request types to actions, it's quite obvious - check this table for a quick run-in.
Jira has a powerful REST API that you can use. This is the main documentation of the current release.
What do you need to do in some high-level steps?:
Set-Up some type of authentication with your JIRA instance. Be it:
Baisc - example
OAuth - example
Get a list of all fields via the API:
The /rest/api/2/field' [method returns a list of all fields][6] - both System and Custom.
Then when you identify the exact field use/rest/api/2/customFieldOption/{id}` to get the full
representation of the Custom Field Option.
I recommend you use a tools like Chrome REST Console ,or anything similar that you can easily make requests with, to get to know the API. The bonus is that you don't need to setUp authentication if you're logged in through the same browser. Your user will require full admin access though.
This is the root of all JIRA REST API docs. Check it out.
If you're doing this in PHP I would personally recommend using some kind of library. I've used
Guzzle (in a CakePHP environment) for this exact task and it turned out very well.
I'm not sure of how do you use the soap API, here is example of using it via the PHP-SOAP:
#!/usr/bin/php -q
<?php
$soapClient = new SoapClient("https://jira.com/rpc/soap/jirasoapservice-v2?wsdl");
$token = $soapClient->login('user', 'password');
$myIssue = $soapClient->getIssue($token,"TES-13");
print_r($myIssue); // all of the issue details
print_r($myIssue->customFieldValues); // get all custom fields
foreach ($myIssue->customFieldValues as $customFieldValue) {
// search for the right custom field
if ($customFieldValue->customfieldId == 'customfield_10402') {
echo $customFieldValue->values[0];
die();
}
}
?>
In case you want to use any other API, have a look at the JIRA Remote API Reference.
A remark regarding the REST and SOAP APIs -To quote from Jira's site the SOAP API "Supported but no future development". The Rest API is still a bit new and there are things you can't yet do with the REST API (example), and can be done easily using the SOAP API.