I've been on this issues for days. I visited the forums, and I have tried different tweaks, yet no solution.
Please can some tell me why my sample javaMail code can't send a mail from any gmail account? Both for SSL and TLS.
Below are my code snippets;
public class EmailUtility {
public static String USERNAME = "???#gmail.com";
public static String PASSWORD = "???";
public static String HOST = "smtp.gmail.com";
public static String PORT = "587";
public static void sendEmail(String toAddress,
String subject, String message) throws AddressException,
MessagingException {
// sets SMTP server properties
Properties properties = new Properties();
properties.put("mail.smtp.host", HOST );
properties.put("mail.smtp.port", PORT );
properties.put("mail.smtp.auth", "true");
properties.put("mail.smtp.starttls.enable", "true");
Authenticator auth = new Authenticator() {
#Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(USERNAME , PASSWORD );
}
};
Session session = Session.getInstance(properties, auth);
// creates a new e-mail message
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(USERNAME ));
InternetAddress[] toAddresses = {new InternetAddress(toAddress)};
msg.setRecipients(Message.RecipientType.TO, toAddresses);
msg.setSubject(subject);
msg.setSentDate(new Date());
msg.setText(message);
// sends the e-mail
Transport.send(msg);
}
}
Related
Right now I am working with the application which automatically logs in user through microsoft account after user enters the credentials once. This is how I am trying to call the microsoft login:
public partial class Startup
{
// Load configuration settings from PrivateSettings.config
private static string appId = ConfigurationManager.AppSettings["ida:AppId"];
private static string appSecret = ConfigurationManager.AppSettings["ida:AppSecret"];
private static string redirectUri = ConfigurationManager.AppSettings["ida:RedirectUri"];
private static string tenantId = ConfigurationManager.AppSettings["ida:tenantId"];
private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
public static string authority = aadInstance + tenantId;
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseKentorOwinCookieSaver();
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = appId,
Authority = authority,
RedirectUri = redirectUri,
TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailedAsync,
AuthorizationCodeReceived = OnAuthorizationCodeReceivedAsync
}
}
);
}
private static Task OnAuthenticationFailedAsync(AuthenticationFailedNotification<OpenIdConnectMessage,
OpenIdConnectAuthenticationOptions> notification)
{
notification.HandleResponse();
string redirect = $"Home/Error?message={notification.Exception.Message}";
if (notification.ProtocolMessage != null && !string.IsNullOrEmpty(notification.ProtocolMessage.ErrorDescription))
{
redirect += $"&debug={notification.ProtocolMessage.ErrorDescription}";
}
notification.Response.Redirect(redirect);
return Task.FromResult(0);
}
private async Task OnAuthorizationCodeReceivedAsync(AuthorizationCodeReceivedNotification notification)
{
var idClient = ConfidentialClientApplicationBuilder.Create(appId)
.WithRedirectUri(redirectUri)
.WithTenantId(tenantId)
.WithClientSecret(appSecret)
.Build();
string email = string.Empty;
try
{
string[] scopes = null;
var result = await idClient.AcquireTokenByAuthorizationCode(
scopes, notification.Code).ExecuteAsync();
email = await GraphHelper.GetUserDetailsAsync(result.AccessToken);
var account = await idClient.GetAccountAsync(result.Account.HomeAccountId.Identifier);
await idClient.RemoveAsync(account);//
}
catch (MsalException ex)
{
System.Diagnostics.Trace.TraceError(ex.Message);
}
notification.HandleResponse();
notification.Response.Redirect($"Account/SignInAzureEmailAsync?email={email}");
}
}
<add key="ida:AADInstance" value="https://login.microsoftonline.com/" />
I read this Microsoft document where is suggested me to use prompt=login which forces user to login every time they click on login button. I couldn't figure out how to apply this modification in my link. Any suggestions please?
You can use RedirectToIdentityProvider function to configure the prompt property
Notifications = new OpenIdConnectAuthenticationNotifications()
{
RedirectToIdentityProvider = context =>
{
context.ProtocolMessage.SetParameter("prompt", "login");
return Task.FromResult(0);
}
}
};
We've got some Azure Functions defined in a class using [FunctionName] attributes from the WebJobs SDK. There are several functions in the class and they all need access to secrets stored in an Azure KeyVault. The problem is that we have many hundreds invocations of the functions a minute, and since each one is making a call to the KeyVault, KeyVault is failing with a message saying something like, "Too many connections. Usually only 10 connections are allowed."
#crandycodes (Chris Anderson) on Twitter suggested making the KeyVaultClient static. However, the constructor we're using for the KeyVaultClient requires a delegate function for the constructor, and you can't use a static method as a delegate. So how can we make the KeyVaultClient static? That should allow the functions to share the client, reducing the number of sockets.
Here's our KeyVaultHelper class:
public class KeyVaultHelper
{
public string ClientId { get; protected set; }
public string ClientSecret { get; protected set; }
public string VaultUrl { get; protected set; }
public KeyVaultHelper(string clientId, string secret, string vaultName = null)
{
ClientId = clientId;
ClientSecret = secret;
VaultUrl = vaultName == null ? null : $"https://{vaultName}.vault.azure.net/";
}
public async Task<string> GetSecretAsync(string key)
{
try
{
using (var client = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetAccessTokenAsync),
new HttpClient()))
{
var secret = await client.GetSecretAsync(VaultUrl, key);
return secret.Value;
}
}
catch (Exception ex)
{
throw new ApplicationException($"Could not get value for secret {key}", ex);
}
}
public async Task<string> GetAccessTokenAsync(string authority, string resource, string scope)
{
var authContext = new AuthenticationContext(authority, TokenCache.DefaultShared);
var clientCred = new ClientCredential(ClientId, ClientSecret);
var result = await authContext.AcquireTokenAsync(resource, clientCred);
if (result == null)
{
throw new InvalidOperationException("Could not get token for vault");
}
return result.AccessToken;
}
}
Here's how we reference the class from our functions:
public class ProcessorEntryPoint
{
[FunctionName("MyFuncA")]
public static async Task ProcessA(
[QueueTrigger("queue-a", Connection = "queues")]ProcessMessage msg,
TraceWriter log
)
{
var keyVaultHelper = new KeyVaultHelper(CloudConfigurationManager.GetSetting("ClientId"), CloudConfigurationManager.GetSetting("ClientSecret"),
CloudConfigurationManager.GetSetting("VaultName"));
var secret = keyVaultHelper.GetSecretAsync("mysecretkey");
// do a stuff
}
[FunctionName("MyFuncB")]
public static async Task ProcessB(
[QueueTrigger("queue-b", Connection = "queues")]ProcessMessage msg,
TraceWriter log
)
{
var keyVaultHelper = new KeyVaultHelper(CloudConfigurationManager.GetSetting("ClientId"), CloudConfigurationManager.GetSetting("ClientSecret"),
CloudConfigurationManager.GetSetting("VaultName"));
var secret = keyVaultHelper.GetSecretAsync("mysecretkey");
// do b stuff
}
}
We could make the KeyVaultHelper class static, but that in turn would need a static KeyVaultClient object to avoid creating a new connection on each function call - so how do we do that or is there another solution? We can't believe that functions that require KeyVault access are not scalable!?
You can use a memory cache and set the length of the caching to a certain time which is acceptable in your scenario. In the following case you have a sliding expiration, you can also use a absolute expiration, depending on when the secrets change.
public async Task<string> GetSecretAsync(string key)
{
MemoryCache memoryCache = MemoryCache.Default;
string mkey = VaultUrl + "_" +key;
if (!memoryCache.Contains(mkey))
{
try
{
using (var client = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetAccessTokenAsync),
new HttpClient()))
{
memoryCache.Add(mkey, await client.GetSecretAsync(VaultUrl, key), new CacheItemPolicy() { SlidingExpiration = TimeSpan.FromHours(1) });
}
}
catch (Exception ex)
{
throw new ApplicationException($"Could not get value for secret {key}", ex);
}
return memoryCache[mkey] as string;
}
}
try the following changes in the helper:
public class KeyVaultHelper
{
public string ClientId { get; protected set; }
public string ClientSecret { get; protected set; }
public string VaultUrl { get; protected set; }
KeyVaultClient client = null;
public KeyVaultHelper(string clientId, string secret, string vaultName = null)
{
ClientId = clientId;
ClientSecret = secret;
VaultUrl = vaultName == null ? null : $"https://{vaultName}.vault.azure.net/";
client = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetAccessTokenAsync), new HttpClient());
}
public async Task<string> GetSecretAsync(string key)
{
try
{
if (client == null)
client = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetAccessTokenAsync), new HttpClient());
var secret = await client.GetSecretAsync(VaultUrl, key);
return secret.Value;
}
catch (Exception ex)
{
if (client != null)
{
client.Dispose();
client = null;
}
throw new ApplicationException($"Could not get value for secret {key}", ex);
}
}
public async Task<string> GetAccessTokenAsync(string authority, string resource, string scope)
{
var authContext = new AuthenticationContext(authority, TokenCache.DefaultShared);
var clientCred = new ClientCredential(ClientId, ClientSecret);
var result = await authContext.AcquireTokenAsync(resource, clientCred);
if (result == null)
{
throw new InvalidOperationException("Could not get token for vault");
}
return result.AccessToken;
}
}
now, the function can use a default static constructor to keep the client proxy:
public static class ProcessorEntryPoint
{
static KeyVaultHelper keyVaultHelper;
static ProcessorEntryPoint()
{
keyVaultHelper = new KeyVaultHelper(CloudConfigurationManager.GetSetting("ClientId"), CloudConfigurationManager.GetSetting("ClientSecret"), CloudConfigurationManager.GetSetting("VaultName"));
}
[FunctionName("MyFuncA")]
public static async Task ProcessA([QueueTrigger("queue-a", Connection = "queues")]ProcessMessage msg, TraceWriter log )
{
var secret = keyVaultHelper.GetSecretAsync("mysecretkey");
// do a stuff
}
[FunctionName("MyFuncB")]
public static async Task ProcessB([QueueTrigger("queue-b", Connection = "queues")]ProcessMessage msg, TraceWriter log )
{
var secret = keyVaultHelper.GetSecretAsync("mysecretkey");
// do b stuff
}
}
You don't actually want KeyVault to scale like that. It is protecting you from racking up unnecessary costs and slow behavior. All you need to do it save the secret for later use. I've created a static class for static instantiation.
public static class KeyVaultHelper
{
private static Dictionary<string, string> Cache = new Dictionary<string, string>();
public static async Task<string> GetSecretAsync(string secretIdentifier)
{
if (Cache.ContainsKey(secretIdentifier))
return Cache[secretIdentifier];
var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetToken));
var secretValue = (await kv.GetSecretAsync(secretIdentifier)).Value;
Cache[secretIdentifier] = secretValue;
return secretValue;
}
private static async Task<string> GetToken(string authority, string resource, string scope)
{
var clientId = ConfigurationManager.AppSettings["ClientID"];
var clientSecret = ConfigurationManager.AppSettings["ClientSecret"];
var clientCred = new ClientCredential(clientId, clientSecret);
var authContext = new AuthenticationContext(authority);
AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);
if (result == null)
throw new InvalidOperationException("Failed to obtain the JWT token");
return result.AccessToken;
}
}
Now in your code, you can do something like this:
private static readonly string ConnectionString = KeyVaultHelper.GetSecretAsync(ConfigurationManager.AppSettings["SqlConnectionSecretUri"]).GetAwaiter().GetResult();
Now whenever you need your secret, it is immediately there.
NOTE: If Azure Functions ever shuts down the instance due to lack of use, the static goes away and is reloaded the next time the function is called. Or you can your own functionality to reload the statics.
Currently I'm working on an app that requires as mandatory a valid email address for the confirmation and validation of the account.
This way..
public void Register(){
string email = "youremail";
if (string.IsNullOrWhiteSpace(email) || !Regex.IsMatch(email, #"\w+([-+.']\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*"))
{
DialogHelper.ShowToast(string.Empty, "The email is invalid");
return;
}
//Continue with your register logic...
}
DialogService.cs
public class DialogService
{
public static void ShowToast(string message, string title)
{
var notificationXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
var toastElement = notificationXml.GetElementsByTagName("text");
toastElement[0].AppendChild(notificationXml.CreateTextNode(title));
toastElement[1].AppendChild(notificationXml.CreateTextNode(message));
var toastNotification = new ToastNotification(notificationXml);
ToastNotificationManager.CreateToastNotifier().Show(toastNotification);
}
}
I've been working with ServiceStack and it's Auth providers. Specifically "FacebookAuthProvider".
My issue here is that the service is called from an iOS app. This app already have a valid access token and i just want to pass this value to servicestack facebook authentication.
I've seen the tests on servicestack github page, but it still doesn't make sense to me.
Is it possible to pass this access token to servicestack, so the authentication skips the part where i ask for permission, since we already did the on the app?
Or am i approching this the wrong way?
Instead of using the builtin facebook auth provider i created my own CustomFacebookAuthProvider.
The reason is that the builtin version needs a browser to redirect the user to facebook for authentication and i didn't need that. I already had an access token.
So based on the official version FacebookAuthProvider.cs i created my own.
using System;
using System.Collections.Generic;
using System.Net;
using Elmah;
using Mondohunter.Backend.BusinessLogic.Interfaces;
using ServiceStack.Common.Extensions;
using ServiceStack.Common.Web;
using ServiceStack.Configuration;
using ServiceStack.ServiceInterface;
using ServiceStack.ServiceInterface.Auth;
using ServiceStack.Text;
using ServiceStack.WebHost.Endpoints;
namespace Mondohunter.Interfaces
{
public class CustomFacebookAuthProvider : OAuthProvider
{
public const string Name = "facebook";
public static string Realm = "https://graph.facebook.com/";
public static string PreAuthUrl = "https://www.facebook.com/dialog/oauth";
public string AppId { get; set; }
public string AppSecret { get; set; }
public string[] Permissions { get; set; }
public CustomFacebookAuthProvider(IResourceManager appSettings)
: base(appSettings, Realm, Name, "AppId", "AppSecret")
{
this.AppId = appSettings.GetString("oauth.facebook.AppId");
this.AppSecret = appSettings.GetString("oauth.facebook.AppSecret");
}
public override object Authenticate(IServiceBase authService, IAuthSession session, Auth request)
{
var tokens = Init(authService, ref session, request);
try
{
if (request.oauth_token.IsNullOrEmpty())
throw new Exception();
tokens.AccessToken = request.oauth_token;
session.IsAuthenticated = true;
var json = AuthHttpGateway.DownloadFacebookUserInfo(request.oauth_token);
var authInfo = JsonSerializer.DeserializeFromString<Dictionary<string, string>>(json);
//Here i need to update/set userauth id to the email
//UpdateUserAuthId(session, authInfo["email"]);
authService.SaveSession(session, SessionExpiry);
OnAuthenticated(authService, session, tokens, authInfo);
//return json/xml/... response;
}
catch (WebException ex)
{
//return json/xml/... response;
}
catch (Exception ex)
{
//return json/xml/... response;
}
}
protected override void LoadUserAuthInfo(AuthUserSession userSession, IOAuthTokens tokens, Dictionary<string, string> authInfo)
{
if (authInfo.ContainsKey("id"))
tokens.UserId = authInfo.GetValueOrDefault("id");
if (authInfo.ContainsKey("name"))
tokens.DisplayName = authInfo.GetValueOrDefault("name");
if (authInfo.ContainsKey("first_name"))
tokens.FirstName = authInfo.GetValueOrDefault("first_name");
if (authInfo.ContainsKey("last_name"))
tokens.LastName = authInfo.GetValueOrDefault("last_name");
if (authInfo.ContainsKey("email"))
tokens.Email = authInfo.GetValueOrDefault("email");
if (authInfo.ContainsKey("gender"))
tokens.Gender = authInfo.GetValueOrDefault("gender");
if (authInfo.ContainsKey("timezone"))
tokens.TimeZone = authInfo.GetValueOrDefault("timezone");
LoadUserOAuthProvider(userSession, tokens);
}
public override void LoadUserOAuthProvider(IAuthSession authSession, IOAuthTokens tokens)
{
var userSession = authSession as CustomUserSession;
if (userSession == null) return;
userSession.Email = tokens.Email ?? userSession.PrimaryEmail ?? userSession.Email;
}
}
}
I hope it makes sense.
I need help with Liferay Autologin and Custom Authentication.
My goal is to get credentials from header (populated by differents authentication framework) and then autologin. I have also to call some services when user login.
I've read some docs (also that one at http://www.liferay.com/community/wiki/-/wiki/Main/Developing+a+Custom+Authentication+System) but still I doesn't understand.
I've done a hook with portal.properties:
auto.login.hooks=it.mypackage.filter.AutoLoginFilter
and the class:
public class AutoLoginFilter implements AutoLogin {
public AutoLoginFilter() {
super();
}
#Override
public String[] login(HttpServletRequest req, HttpServletResponse arg1) throws AutoLoginException {
String[] credentials = new String[] { "test#liferay.com" };
return credentials;
}
}
In the example class AutoLogin I suppose to return just the username (I doesn' need to verify other credentials).
Then I create a ext with portal-ext.properties:
auth.pipeline.pre=it.mypackage.auth.MyAuthenticator
auth.pipeline.enable.liferay.check=false
and the authenticator:
public class MyAuthenticator implements Authenticator {
private static Log _log = LogFactory.getLog(SwaFiamAuthenticator.class);
#Override
public int authenticateByEmailAddress(long companyId, String emailAddress, String password,
Map<String, String[]> headerMap, Map<String, String[]> parameterMap) throws AuthException {
return authenticate();
}
#Override
public int authenticateByScreenName(long companyId, String screenName, String password,
Map<String, String[]> headerMap, Map<String, String[]> parameterMap) throws AuthException {
return authenticate();
}
#Override
public int authenticateByUserId(long companyId, long userId, String password, Map<String, String[]> headerMap,
Map<String, String[]> parameterMap) throws AuthException {
return authenticate();
}
protected int authenticate() {
_log.debug("returning SUCCESS");
return SUCCESS;
}
}
What I expect from the code is:
Every user entering the portal is automatically authenticated without seeing any login page, and is recognized as user "test#liferay.com"
What I get:
AutoLoginFilter.login is called, but the user is still redirected to login page.
MyAuthenticator never called (it's called only if I remove AutoLogin-hook and
remove also auth.pipeline.enable.liferay.check=false property).
Thanks for help.
The returned array must contains at first the userId, something like this must work:
String[] credentials = new String[3];
credentials[0] = userId;
credentials[1] = "undefined";
credentials[2] = Boolean.FALSE.toString();
the userId you can find in Control Panel -> Users ->...
or (better way) load it programmaticaly with UserLocalServiceUtil.getUserByEmailAddress(companyId, emailAddress);
the auth.pipeline is not needed for this approach.