Authentication with SMTP transport using Swiftmailer - authentication

I'm using Swiftmailer to send emails in my Yii based application and it works great, so there is no problems with the Swiftmailer extension wrapper. But now I want to use the SMPT transport to authenticate the users in my application against the mail server. The code I'm using:
$SM = Yii::app()->swiftMailer;
$mailHost = 'XXX';
$mailPort = XXX;
// New transport
$transport = $SM->smtpTransport($mailHost, $mailPort);
$transport->setUsername($username);
$transport->setPassword($password);
$transport->start();
if($transport->isStarted()){
// authenticated;
}else{
// error;
}
$transport->stop();
This isn't working. When I set real login credentials instantly logs in. But when I type wrong ones, it spends some time but at last it logs in too. I don't know why this happens because just when using real credentials Swiftmailer can send emails.
I'm using the right API functions? I'm doing something wrong?

Looking at the source, when you call start(), started is always set to True.
I'm not familiar with switfmailer, but it looks like you'll want to check the results of authenticate()

Related

Session lost after redirect SAML: may be different webapps?

I am fairly new to webapps programming, so I thought of asking here.
I am implementing the SAML2 protocol in an open source app (namely OFBiz) but I am encountering a problem related to session loss after the protocol made its course.
I am following these steps to implement the protocol. Suppose ofbizwebsite.com is the URL of the site.
Installed a custom plugin named SAMLIntegration which exposes the ACS page and the logic for login. To my understanding, a plugin (gradle) is like an indipendent java project, which translates to a new set of resources for the application (the plugin enables, for example, to visit ofbizwebsite.com/SAMLIntegration and setup some resources).
Exposed the ACS page to ofbizwebsite.com/SAMLIntegration/control/acs, as well as metadata ofbizwebsite.com/SAMLIntegration/control/metadata.jsp
Created the logic for login. Basically, an entity called UserLogin is saved in the session and recovered by a "checker" to understand if an user is logged in. Suppose that this checker is a HTTP WebEvent handler which can be called by any resource requiring authentication.
Now, the problem. If redirect the user to a resource on SAMLIntegration (for example ofbizwebsite.com/SAMLIntegration/control/aview or any ofbizwebsite.com/SAMLIntegration/control/* by calling response.sendRedirect("aview")) check works and login is preserved. Visiting any resource (for example ofbizwebsite.com/aplugin/control/anotherview) by navigating the application does not preserve the session.
OFBiz use internally a mechanism for preserving the userLogin between webapps, by creating an HashMap between and UUID and a UserLogin object. The UUID is passed between two different resources, appending this key to each path (so ofbizwebsite.com/aplugin/control/anotherview?externalKey=THEEFFECTIVEUUID)
To my understanding, changing from ofbizwebsite.com/SAMLIntegration/control/* to ofbizwebsite.com/aplugin/control/* determine a session loss. So, my idea was to replace the UUID mechanism with SAML2. However, I do not know how to solve this problem.
In particular, I would like to execute a SAML request each time the checker function is executed. If I can't find the user in the session, a SAML request is fired. However, my problem is HOW to manage the response. Normally, I would redirect it to the acs ofbizwebsite.com/SAMLIntegration/control/acs. Doing so, however, does not allow me to handle the response in the checker function, as the control is passed to another servlet by an external request (the SAML response fired by the IdP). Should I provide a different acs for each different path? (so one for SAMLIntegration and one for aplugin?) And, even if this was the case, how can I return the control to the checker function which has invoked the SAML request?
Here you go for installing the Shibboleth HTTPD module: https://pad.nereide.fr/SAMLWithShibboleth
You also need this method somewhere in OFBiz (I recommend LoginWorker.java, but you can put it where you want). It allows to use the externalAuthId of the userLogin for authentication, with the uid returned by the sso:
public static String checkShibbolethRequestRemoteUserLogin(HttpServletRequest request, HttpServletResponse response) {
LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
Delegator delegator = dispatcher.getDelegator();
// make sure the user isn't already logged in
if (!LoginWorker.isUserLoggedIn(request)) {
String remoteUserId = (String) request.getAttribute("uid"); // This is the one which works, uid at Idp, remoteUserId here
if (UtilValidate.isNotEmpty(remoteUserId)) {
//we resolve if the user exist with externalAuthId
String userLoginId = null;
GenericValue userLogin;
try {
List<GenericValue> userLogins = delegator.findList("UserLogin",
EntityCondition.makeConditionMap("externalAuthId", remoteUserId, "enabled", "Y"),
null, null, null, true);
userLogin = userLogins.size() == 1 ? userLogins.get(0) : null;
} catch (GenericEntityException e) {
Debug.logError(e, module);
return "error";
}
if (userLogin != null) {
userLoginId = userLogin.getString("userLoginId");
}
//now try to log the user found
return LoginWorker.loginUserWithUserLoginId(request, response, userLoginId);
}
}
return "success";
}
You also need to have this method as an OFBiz preprocessor in the webapp controllers. I suggest to have a look at common-controller.xml.
Finally you need the configs that redirect to the SSO page if no session. That should do the job, at least it works for them...
Finally I recommend https://www.varonis.com/blog/what-is-saml in case of need.

Create a space with Google Chat REST API

We have a program that uses a service account to manage various thing inside Google Chat.
Now, we have the need to create a new space using the Google Chat REST API (spaces.create).
We already joined the developer preview program, as this endpoint is not yet generally available.
From what we understand, this endpoint is not possible to invoke via service account and so we wanted to ask you… can we invoke this endpoint automatically using “domain delegation”? If yes, how?
We always want to use the service account as it is not possible to show a login prompt to the user.
We enabled the domain delegation but that endpoint returns always status 403. (We are using Google.Apis library for .NET Core
using Google.Apis.Auth.OAuth2;
var credential = GoogleCredential.FromFile("key.json")
.CreateScoped("https://www.googleapis.com/auth/chat.spaces.create")
.CreateWithUser("service-account-email#project.iam.gserviceaccount.com");
var token = await credential.UnderlyingCredential.GetAccessTokenForRequestAsync();
HttpRequestMessage request = new(HttpMethod.Post, "https://chat.googleapis.com/v1/spaces");
request.Headers.Authorization = new("Bearer", token);
var payload = #"
{
""name"": ""testspace-1"",
""spaceType"": ""SPACE"",
""singleUserBotDm"": true,
""displayName"": ""Test Space""
}
";
request.Content = new StringContent(payload, System.Text.Encoding.UTF8, "application/json");
HttpClient client = new();
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
If you check the documentation Auth
You will notice it stats that service account authorization is supported. If you are part of thedeveloper preview program
The reason I asked about your code is that the last time i tried this which notably was a while ago. The google .net client library was not generated the methods that were under preview.
So while it may work yes. The issue your may have is that the client library when loaded will not have the method you need meaning you will have to code the call to the endpoint yourself.
If this is in fact the case let me know if you have any issues peceing it together I may be able to help.
update your code
There is an error in your code
.CreateWithUser("service-account-email#project.iam.gserviceaccount.com");
The email in CreateWithUser should be the user on your domain who you wish to delicate the service account as. Not the service account email address.

OWIN cookie authentication OnValidateIdentity should be called on every request?

Perhaps I am misunderstanding how this works, but I thought the OnValidateIdentity would be called on every HTTP request to the server. I see it get hit on initial login (a bunch of times, so it looks like it is every HTTP request on initially), but then it doesn't seem to get called again. I let my app sit there until it should be expired, but it never gets hit again on subsequent requests to the server, until I logout and login again.
I have set my expiry very low and turned off sliding expiration to see if I could get it to fail, but to no avail.
Should I not see the OnValidateIdentity get called on every HTTP request? Ultimately, I really just want a cookie expiry to result in a logout. I assumed I had to check the expiry on each request in the OnValidateIdentity, but if this is not the way to do it please let me know!
Am I misunderstanding how this work, or how I should be using cookie expiries to force a logout?
Here is my basic setup:
app.UseCookieAuthentication(New CookieAuthenticationOptions() With
{
.AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
.AuthenticationMode = AuthenticationMode.Active,
.ExpireTimeSpan = TimeSpan.FromMinutes(1.0),
.SlidingExpiration = False,
.Provider = New CookieAuthenticationProvider() With
{
.OnValidateIdentity = SecurityStampValidator.OnValidateIdentity(Of ApplicationUserManager, ApplicationUser, Integer)(
validateInterval:=TimeSpan.FromMinutes(1.0),
regenerateIdentityCallback:=Async Function(manager, user)
Return Await user.GenerateUserIdentityAsync(manager, DefaultAuthenticationTypes.ApplicationCookie)
End Function,
getUserIdCallback:=Function(id) id.GetUserId(Of Integer)())
},
.LoginPath = New PathString("/Account/Login")
})
Probably a bit late...
To use cookie Expiry, that's delegated to the browser. If a cookie expires, then the browser wouldn't send it.
OnValidateIdentity is called on every request. If you want to debug it, pull it out into a new method and debug from that method instead.
However, the identity itself is only validated against the database when the validationInterval is passed.

Extra authentication criteria

I'm trying to implement an extra authentication layer with the purpose of authenticating the user only if he has a certain status.
If the status is different, I want to show a custom login error (Your account has been suspended) and not authenticate the user at all, similar to what happens if the credentials are wrong, but with a different error message.
So far I've tried two options:
I've added a check within a listener that checks for an "InteractiveLoginEvent". Here I can check the user status and set a flash error message but I don't see what's the proper way to redirect back to the login page, since this event has no response method, other than using a header() call which I definitely want to avoid.
I implemented a custom voter, set the "access_decision_manager" startegy to "unanimous" and returned "ACCESS_DENIED" if the status is not allowing the user to authenticate. So far so good, the user cannot access the resources but I see he still gets authenticated. And I definitely don't want that.
I'm not for sure if I'm missing something or if I'm going in the wrong direction.
Since symfony 2 makes a clear difference between authentication and authorization seems that option 2) is related to authorization, so option 1) is more suitable.
So among the "InteractiveLoginEvent" listener I just added the proper check for the user status and by throwing the following exception I managed to implement my functionality as needed:
throw new AuthenticationException('suspend error message');
So the listener looks something like this:
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
if ($this->securityContext->isGranted('ROLE_CUSTOMROLE')) {
$user = $this->securityContext->getToken()->getUser();
// ... check for the user status here
throw new AuthenticationException('Your account has been suspended!');
}
}

Windows Phone and Website Request

I wish to send a request to a Website (server) to update a potential scoreboard which everyone who has the application can see. This website isn't of course restricted to just the application users - but it can be accessible to anyone.
Is it possible to call a WCF from a Windows Phone app for example where the WCF can then update the database. So whenever someone goes on the website, the updated changes will be seen.
Is this at all possible? And if it is, would this be the most sensible/optimised way of doing things?
I did this using a BsckgroundWorker in my ViewModel to prevent hanging the UI. This way, you can "set it and forget it". Something like this:
private void UpdateScoreboard()
{
var scoreboardWorker = new BackgroundWorker();
scoreboardWorker.DoWork += (s,dwe)=>{
//call some WCF service compleate async
};
scoreboardWorker.RunWorkerCompleted += (s,rwe)=>{
// check whether rwe.Error is not null, indicating an exception. Show an alert maybe
};
scoreboardWorker.RunWorkerAsync();
}