FromsAuthenticationTicket.UserData is always empty and authentication cookie does not retain value - c#

I have the following code in the Login(username, password)
if (hasher.Compare(password, person.Hash))
{
FormsAuthentication.SetAuthCookie(userId, true);
OpenAccount(person);
var principle = new GenericPrincipal( new GenericIdentity($"{person.FirstName} {person.LastName}"), new string[] {"All"});
var data = Konstants.Serialize(principle);
var ticket = new FormsAuthenticationTicket(1, principle.Identity.Name, DateTime.Now, DateTime.Now.AddMinutes(30), true, data);
var encryptedTicket = FormsAuthentication.Encrypt(ticket);
FormsAuthentication.SetAuthCookie(principle.Identity.Name, false);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
Response.SetCookie(cookie);
Response.RedirectToRoute("Default");
}
Then in the Global.asax I have the following code:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
var authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
try
{
if (authCookie != null)
{
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(authCookie.Value);
if (!string.IsNullOrEmpty(ticket.UserData))
{
var principle = Konstants.Deserialize<GenericPrincipal>(ticket.UserData);
HttpContext.Current.User = principle;
}
}
}
catch
{
}
}
But in the AutheticateRequest the ticket.UserData is always empty. In fact the cookie value I get is the one that was before authentication not the one that I stored. What am I doing wrong here.
Update: The Serialize and Deserialize code is as follows:
public static string Serialize<T>(T obj)
{
var ret = string.Empty;
using(var ms = new MemoryStream())
{
var bf = new BinaryFormatter();
bf.Serialize(ms, obj);
ret= Convert.ToBase64String(ms.GetBuffer());
}
return ret;
}
public static T Deserialize<T>(string text)
{
var obj = default(T);
var data = Convert.FromBase64String(text);
using(var ms = new MemoryStream(data, false))
{
var bf = new BinaryFormatter();
obj = (T)bf.Deserialize(ms);
}
return obj;
}

You've got two calls to SetAuthCookie in that first code block, but you don't need either if you're creating a custom ticket. I think this should do the trick:
OpenAccount(person);
var principle = new GenericPrincipal( new GenericIdentity($"{person.FirstName} {person.LastName}"), new string[] {"All"});
var data = Konstants.Serialize(principle);
var ticket = new FormsAuthenticationTicket(1, principle.Identity.Name, DateTime.Now, DateTime.Now.AddMinutes(30), true, data);
var encryptedTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
Response.SetCookie(cookie);
Response.RedirectToRoute("Default");
Edit: I also just noticed that you're not passing your serialized data into the userData field of the new ticket, is that the intention?

Related

Unprotected msg file cannot be inspected, CorrelationId=663b265e-5e60-421f-92a3-ad301a87a272, CorrelationId.Description=FileHandler

I am trying to decrypt an encrypted mail using MIP SDK. I have used application level API permission and able to authenticate via authdelegate but not sure after authentication I am getting Error message :NotSupportedException: Unprotected msg file cannot be inspected, CorrelationId=663b265e-5e60-421f-92a3-ad301a87a272, CorrelationId.Description=FileHandler .
Controller Code Snippet:
private JObject get_mail_details(string client_name, string client_id, string client_secret, string tenant_id, string generic_mail_box, string rpmsg_file_path)
{
try
{
IDictionary<string, string> app_info = new Dictionary<string, string>();
app_info.Add("client_id", client_id);
app_info.Add("client_secret", client_secret);
app_info.Add("tenant_id", tenant_id);
ApplicationInfo mip_app_info = new ApplicationInfo()
{
ApplicationId = client_id,
ApplicationName = client_name,
ApplicationVersion = "1.0.0"
};
// Instantiate the AuthDelegateImpl object, passing in AppInfo.
AuthDelegateImplementation authDelegate = new AuthDelegateImplementation(app_info);
MipContext mipContext = MIP.CreateMipContext(mip_app_info, "mip_data", Microsoft.InformationProtection.LogLevel.Trace, null, null);
// Initialize and instantiate the File Profile.
// Create the FileProfileSettings object.
// Initialize file profile settings to create/use local state.
var profileSettings = new FileProfileSettings(mipContext,
CacheStorageType.OnDiskEncrypted,
new ConsentDelegateImplementation());
var fileProfile = Task.Run(async () => await MIP.LoadFileProfileAsync(profileSettings)).Result;
//Console.WriteLine(fileProfile);
var customSettings = new List<KeyValuePair<string, string>>();
//Console.WriteLine(customSettings);
customSettings.Add(new KeyValuePair<string, string>("enable_msg_file_type", "true"));
var engineSettings = new FileEngineSettings(generic_mail_box, authDelegate, "", "en-US");
engineSettings.Identity = new Identity(generic_mail_box);
engineSettings.CustomSettings = customSettings;
var fileEngine = Task.Run(async () => await fileProfile.AddEngineAsync(engineSettings)).Result;
IFileHandler fileHandler = Task.Run(async () => await fileEngine.CreateFileHandlerAsync(rpmsg_file_path,
rpmsg_file_path,
true)).Result;
Console.WriteLine(fileHandler);
IMsgInspector msgInspector = (IMsgInspector)Task.Run(async () => await fileHandler.InspectAsync()).Result;
ASCIIEncoding encoding = new ASCIIEncoding();
Console.WriteLine(msgInspector.CodePage);
Console.WriteLine(Encoding.UTF8.GetString(msgInspector.Body.ToArray()));
Console.WriteLine(msgInspector.Body.ToArray());
//Console.WriteLine(ConvertToText(hello));
byte[] mail_body_byte_array = msgInspector.Body.ToArray();
string mail_body = "";
string mail_body_encoding = "";
var writer = new BinaryWriter(File.OpenWrite("abc.rtf"));
writer.Write(mail_body_byte_array);
writer.Dispose();
using (StreamReader reader = new StreamReader(new MemoryStream(mail_body_byte_array),
detectEncodingFromByteOrderMarks: true))
{
mail_body = reader.ReadToEnd();
mail_body_encoding = reader.CurrentEncoding.ToString();
}
string pattern = "(<html.*</html>)";
Match html_text_body = Regex.Match(mail_body, pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
mail_body = html_text_body.Groups[0].ToString();
//mail_body = ConvertToText(mail_body);
JObject json_data = new JObject
{
["mail_body"] = mail_body,
["mail_body_encoding"] = mail_body_encoding,
["mail_body_type"] = msgInspector.BodyType.ToString()
};
JObject json_resp = new JObject
{
["status"] = "Success",
["data"] = json_data
};
return json_resp;
}
catch (Exception ex)
{
JObject json_resp = new JObject
{
["status"] = "Failure",
["message"] = "Some error occurred (Please try again after sometime)"
};
LOGGER.Log(Microsoft.Extensions.Logging.LogLevel.Error, Server.LineNumber(), "Error occurred while getting mail details");
LOGGER.Log(Microsoft.Extensions.Logging.LogLevel.Error, Server.LineNumber(), ex.StackTrace);
return json_resp;
}
}

Receiving 403 error with Users.Messages.Send in Gmail API

I'm trying to call Send on the GmailService from a C# .NET MVC app. and I keep getting a 403 error when I call send.
I've checked my scopes, the Gmail setup definitely has the Gmail API enabled, and my ClientID and ClientSecret are fresh.
var httpClient = new HttpClient{
BaseAddress = new Uri("https://www.googleapis.com")
};
var requestUrl = $"oauth2/v4/token?code={code}&client_id={ClientId}&client_secret={SecretKey}&redirect_uri={RedirectUrl}&grant_type=authorization_code";
var dict = new Dictionary<string, string>{
{ "Content-Type", "application/x-www-form-urlencoded" }
};
var req = new HttpRequestMessage(HttpMethod.Post, requestUrl){Content = new FormUrlEncodedContent(dict)};
var response = await httpClient.SendAsync(req);
var token = JsonConvert.DeserializeObject<GmailToken>(await response.Content.ReadAsStringAsync());
Session["user"] = token.AccessToken;
//var obj = await GetuserProfile(token.AccessToken);
var obj = await DoSendEmail(token);
public void DoSendEmail(GmailToken inToken) {
const string fromAcct = "XXXXXXXX#gmail.com";
TokenResponse token = new TokenResponse();
token.AccessToken = inToken.AccessToken;
token.ExpiresInSeconds = inToken.ExpiresIn;
token.IdToken = inToken.IdToken;
token.TokenType = inToken.TokenType;
token.IssuedUtc = DateTime.UtcNow;
IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer {
ClientSecrets = secrets,
Scopes = SCOPES,
ProjectId = "Xcent CP"
});
UserCredential credential = new UserCredential(flow, fromAcct, token);
if (credential.Token.IsExpired(credential.Flow.Clock)) {
bool success = credential.RefreshTokenAsync(CancellationToken.None).Result;
if (!success) {
throw new Exception("Could not refresh token");
}
}
GmailService gs = null;
try {
gs = new GmailService(new Google.Apis.Services.BaseClientService.Initializer() {
ApplicationName = APP_NAME,
HttpClientInitializer = credential
});
var mailMessage = new System.Net.Mail.MailMessage();
mailMessage.From = new System.Net.Mail.MailAddress(fromAcct);
mailMessage.To.Add("XXXXXXXX#comcast.net");
mailMessage.ReplyToList.Add(fromAcct);
mailMessage.Subject = "Test email";
mailMessage.Body = "<html><body>Hi <b>Lee</b>, this is <b>yet another</b> test message.</body></html>";
mailMessage.IsBodyHtml = true;
var mimeMessage = MimeKit.MimeMessage.CreateFromMailMessage(mailMessage);
var gmailMessage = new Google.Apis.Gmail.v1.Data.Message {
Raw = Encode(mimeMessage.ToString())
};
gs.Users.Messages.Send(gmailMessage, fromAcct).Execute();
}
catch (Exception ex) {
throw ex;
}
finally {
if (gs != null) {
gs.Dispose();
}
gs = null;
}
}
I'm not sure where to look...I've been through many many many online articles and tutorials, tried seemingly everything, and I'm still stuck with the 403 error. Help!
Thanks,
Lee
So after many hours spent looking at this I figured out the problem. My link to the Google login was this:
Response.Redirect($"https://accounts.google.com/o/oauth2/v2/auth?client_id={ClientId}&response_type=code&scope=openid%20email%20profile&redirect_uri={RedirectUrl}&state=abcdef");
"openid%20email%20profile" was the only scope I was specifying for the login, hence the 403 error about the scope I was using for the flow variable.
phew!

Verifying a JWT signature using azure keyvault always returns false

I'm trying to verify a signature using Azure keyvault client, however it's always returning false.
I've managed to sign it using the KeyVaultClient.SignAsync method however when attempting to use KeyVaultClient.VerifyAsync the result always comes back false.
// Added for completeness, this method seems to be working correctly
private static async Task<string> SignJwt(KeyVaultClient client)
{
var claimsToSign = new[]
{
new Claim("sub", "UserId123"),
new Claim("custom", "MyValue")
};
var token = new JwtSecurityToken(
issuer: "AuthApp",
audience: "Consumer",
claims: claimsToSign
);
var header = Base64UrlEncoder.Encode(JsonConvert.SerializeObject(new Dictionary<string, string>()
{
{JwtHeaderParameterNames.Alg, JsonWebKeySignatureAlgorithm.ES256},
{JwtHeaderParameterNames.Typ, "JWT"}
}));
var byteData = Encoding.UTF8.GetBytes(header + "." + token.EncodedPayload);
var hasher = new SHA256CryptoServiceProvider();
var digest = hasher.ComputeHash(byteData);
var signature = await client.SignAsync(KeyVaultBaseUrl, KeyName, KeyVersion, JsonWebKeySignatureAlgorithm.ES256, digest);
var fullJwt = $"{header}.{token.EncodedPayload}.{Base64UrlEncoder.Encode(signature.Result)}";
return fullJwt;
}
// This always returns a false result
private static async Task<KeyVerifyResult> ValidateJwt()
{
// Example of a JWT produced by the SignJwt method
var jwt = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJVc2VySWQxMjMiLCJjdXN0b20iOiJNeVZhbHVlIiwiaXNzIjoiQXV0aEFwcCIsImF1ZCI6IkNvbnN1bWVyIn0.6tYkBcoFojJVJBhdNST49v4A3VWC1Rqizx_FzmSRICQubDEfXVopfP7Rs9tOBi9YzTCbod9o3hmHzIxANoIh7A";
var client = new KeyVaultClient(GetAccessTokenAsync, new HttpClient());
var jwtParts = jwt.Split('.');
var header = jwtParts[0];
var body = jwtParts[1];
var signature = Encoding.UTF8.GetBytes(Base64UrlEncoder.Decode(jwtParts[2]));
var byteData = Encoding.UTF8.GetBytes($"{header}.{body}");
var hasher = new SHA256CryptoServiceProvider();
var digest = hasher.ComputeHash(byteData);
var verified = await client.VerifyAsync(KeyVaultBaseUrl, KeyName, KeyVersion, JsonWebKeySignatureAlgorithm.ES256, digest, signature);
return verified;
}
private static async Task<string> GetAccessTokenAsync(string authority, string resource, string scope)
{
var appCredentials = new ClientCredential(ClientId, ClientSecret);
var context = new AuthenticationContext(authority, TokenCache.DefaultShared);
var result = await context.AcquireTokenAsync(resource, appCredentials);
return result.AccessToken;
}
Any ideas why ValidateJwt always returns false instead of true?
Solved it.
For anyone interested I wasn't properly base 64 encoding the signature in the SignJwt method:
Instead of using Base64UrlEncoder.Encode/Decode, use Convert.ToBase64String/FromBase64String
For the code snippet in the question to work, I needed to update the SignJwt and ValidateJwt methods to:
private static async Task<string> SignJwt(KeyVaultClient client)
{
var claimsToSign = new[]
{
new Claim("sub", "UserId123"),
new Claim("custom", "MyValue")
};
var token = new JwtSecurityToken(
issuer: "AuthApp",
audience: "Consumer",
claims: claimsToSign
);
var header = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Dictionary<string, string>()
{
{JwtHeaderParameterNames.Alg, JsonWebKeySignatureAlgorithm.ES256},
{JwtHeaderParameterNames.Typ, "JWT"}
})));
var byteData = Encoding.UTF8.GetBytes(header + "." + token.EncodedPayload);
var hasher = new SHA256CryptoServiceProvider();
var digest = hasher.ComputeHash(byteData);
var signature = await client.SignAsync(KeyVaultBaseUrl, KeyName, KeyVersion, JsonWebKeySignatureAlgorithm.ES256, digest);
var fullJwt = $"{header}.{token.EncodedPayload}.{Base64UrlEncoder.Encode(signature.Result)}";
return fullJwt;
}
private static async Task<KeyVerifyResult> ValidateJwt()
{
// Example of a JWT produced by the SignJwt method
var jwt = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJVc2VySWQxMjMiLCJjdXN0b20iOiJNeVZhbHVlIiwiaXNzIjoiQXV0aEFwcCIsImF1ZCI6IkNvbnN1bWVyIn0.6tYkBcoFojJVJBhdNST49v4A3VWC1Rqizx_FzmSRICQubDEfXVopfP7Rs9tOBi9YzTCbod9o3hmHzIxANoIh7A";
var client = new KeyVaultClient(GetAccessTokenAsync, new HttpClient());
var jwtParts = jwt.Split('.');
var header = jwtParts[0];
var body = jwtParts[1];
var signature = Encoding.UTF8.GetBytes(Convert.FromBase64String(jwtParts[2]));
var byteData = Encoding.UTF8.GetBytes($"{header}.{body}");
var hasher = new SHA256CryptoServiceProvider();
var digest = hasher.ComputeHash(byteData);
var verified = await client.VerifyAsync(KeyVaultBaseUrl, KeyName, KeyVersion, JsonWebKeySignatureAlgorithm.ES256, digest, signature);
return verified;
}

How to add a time stamp on digital signature using cmsSigner

I trying to set the time stamp on my signature using SignedCms, I succeeded in returning the timestamptoken of castle bouncy but I need to implement time stamp of the authorization server on my signature.
I've tried adding UnsignedAttributes but to no avail.
This is my signature code:
static public byte[] SignMsg(Byte[] msg, X509Certificate2 signerCert, bool detached, Arquivo arquivo)
{
ContentInfo contentInfo = new ContentInfo(msg);
SignedCms signedCms = new SignedCms(contentInfo, detached);
CmsSigner cmsSigner = new CmsSigner(signerCert);
cmsSigner.IncludeOption = X509IncludeOption.EndCertOnly;
NetworkCredential myCred = new NetworkCredential(
"user", "pass");
CredentialCache myCache = new CredentialCache();
myCache.Add(new Uri("http://tsatest2.digistamp.com/tsa"), "Basic", myCred);
UserCredentials user = new UserCredentials(myCred);
var d = RequestTimeStampToken("http://tsatest2.digistamp.com/tsa", arquivo.arquivo,null, user);
var x = d.Time;
var chain = new X509Chain();
System.Security.Cryptography.AsnEncodedData timeData = new Pkcs9AttributeObject(Oid.SHA256.OID, d.EncodedToken);
cmsSigner.UnsignedAttributes.Add(timeData);
signedCms.ComputeSignature(cmsSigner, false);
return signedCms.Encode();
}
This is my response from request:
public static TimeStampToken RequestTimeStampToken(string tsaUri, string pathToFile)
{
return RequestTimeStampToken(tsaUri, pathToFile, null, null);
}
public static TimeStampToken RequestTimeStampToken(string tsaUri, string pathToFileToTimestamp, Oid digestType, UserCredentials credentials)
{
if (null == pathToFileToTimestamp)
{
throw new ArgumentNullException("pathToFileToTimestamp");
}
using (FileStream fs = new FileStream(pathToFileToTimestamp, FileMode.Open, FileAccess.Read))
{
return RequestTimeStampToken(tsaUri, fs, digestType, credentials);
}
}
public static TimeStampToken RequestTimeStampToken(string tsaUri, Stream dataToTimestamp, Oid digestType, UserCredentials credentials)
{
if (null == tsaUri)
{
throw new ArgumentNullException("tsaUri");
}
if (null == dataToTimestamp)
{
throw new ArgumentNullException("dataToTimestamp");
}
if (null == digestType)
{
digestType = Oid.SHA512;
}
byte[] digest = DigestUtils.ComputeDigest(dataToTimestamp, digestType);
Request request = new Request(digest, digestType.OID);
return RequestTST(tsaUri, request, credentials);
}
private static TimeStampToken RequestTST(string tsaUri, Request request, UserCredentials credentials = null)
{
byte[] responseBytes = null;
UriBuilder urib = new UriBuilder(tsaUri);
switch (urib.Uri.Scheme)
{
case "http":
case "https":
responseBytes = GetHttpResponse(tsaUri, request.ToByteArray(), credentials);
break;
case "tcp":
responseBytes = GetTcpResponse(tsaUri, request.ToByteArray());
break;
default:
throw new TimeStampException("Unknown protocol.");
}
Response response = new Response(responseBytes);
ValidateResponse(request, response);
return response.TST;
}
public Response(byte[] response)
{
if (null == response)
{
throw new ArgumentNullException("response");
}
this.response = new TimeStampResponse(response);
if (null != this.response.TimeStampToken)
{
Org.BouncyCastle.Asn1.Tsp.TimeStampResp asn1Response = Org.BouncyCastle.Asn1.Tsp.TimeStampResp.GetInstance(Org.BouncyCastle.Asn1.Asn1Sequence.FromByteArray(response));
var derTst = asn1Response.TimeStampToken.GetDerEncoded();
this.TST = new TimeStampToken(derTst);
}
}
I want to include the time stamp in the digital signature and information that it has been validated by an authorization server.
This works for me.
cmsSigner.SignedAttributes.Add(new Pkcs9SigningTime(DateTime.Now));

How to read authentication cookie set in wcf service from android client application

Hi i developed a Wcf service using form authentication and there is a login service Method to authenticate the client.
This method returns the authentication cookie.
HttpCookie cookie = null;
returnValue = Membership.ValidateUser(userName, password);
if (returnValue)
{
var ticket = new FormsAuthenticationTicket(
1,
userName,
DateTime.Now,
DateTime.Now.AddMinutes(5),
true,
userName // or user.UserID or other info you might find appropriate
);
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
HttpContext.Current.Response.Cookies.Add(cookie);
}
return returnValue;
All i want to know is how a android client can call this log in service and get the cookie.
I know how to consume using c# as bellow.But i want to do same stuff from a android Mobile.So please give suggestion to the below code from android Version.
var sharedCookie = string.Empty;
bool isValid;
string data = string.Empty;
var authClient = new LoginServiceClient();
using (new OperationContextScope(authClient.InnerChannel))
{
isValid = authClient.Login("admin1", "outreach#");
if (isValid)
{
var response = (HttpResponseMessageProperty)OperationContext.Current.IncomingMessageProperties[HttpResponseMessageProperty.Name];
sharedCookie = response.Headers["Set-Cookie"];
}
}
if (isValid)
{
var request = (HttpWebRequest)WebRequest.Create("http://localhost:48090/CustomService/GetAgencies");
request.Headers["Cookie"] = sharedCookie;
var responce = (HttpWebResponse)request.GetResponse();
using (var stream = responce.GetResponseStream())
{
using (var reader = new StreamReader(stream))
{
data = reader.ReadToEnd();
}
}
}
Please let us know if you need any firther information.

Categories