I use Fiddler dll to install Fiddler certificates:
public static bool InstallCertificate()
{
if (!string.IsNullOrEmpty(certmakerBcCert))
{
FiddlerApplication.Prefs.SetStringPref("fiddler.certmaker.bc.key", certmakerBcKey);
FiddlerApplication.Prefs.SetStringPref("fiddler.certmaker.bc.cert", certmakerBcCert);
}
if (!CertMaker.rootCertExists())
{
//CLog.writeNoLogInDB("Creating SSL certificate");
if (!CertMaker.createRootCert())
return false;
if (!CertMaker.trustRootCert())
return false;
certmakerBcCert = FiddlerApplication.Prefs.GetStringPref("fiddler.certmaker.bc.cert", null);
certmakerBcKey = FiddlerApplication.Prefs.GetStringPref("fiddler.certmaker.bc.key", null);
}
return true;
}
I would need to export the RootCertificate file that is created through code. Is there a method to do so?
(I know this is old, but incase you haven't found the answer or someone else is searching)
Based on your code it looks like your using the BouncyCastle certificate maker, so you can do this to export the root certficiate:
FiddlerApplication.Prefs.SetBoolPref("fiddler.certmaker.bc.EmitRootCertFile", true)
This will dump a "FiddlerBCRoot.pfx" on your desktop with an empty password
Related
Good day!
I am new to Google Play Services and want to save JSON(string) into the cloud and it doesn't work. I narrowed down a problem through phone and debug texts and realized that a function from ((PlayGamesPlatform)Social.Active).SavedGame.OpenWithAutomaticConflictResolution is not called which is strange because in the tutorial that I watched everything worked and the user logged in successfuly.
here is a code snippet with a comments and a function that is not invoked(I can send a whole script if needed also). Is there something else I am missing?
public void OpenSaveToCloud(bool saving)
{
// debugtext.text = "hello";
if(Social.localUser.authenticated)
{
debugtext.text = "Authorized and proceed to save";
issaving = saving;
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithAutomaticConflictResolution
(SAVE_NAME, GooglePlayGames.BasicApi.DataSource.ReadCacheOrNetwork,
ConflictResolutionStrategy.UseLongestPlaytime, SavedGameOpen); //SavedGame open must be called
}
else{
debugtext.text = "No authentication";
}
}
private void SavedGameOpen(SavedGameRequestStatus status, ISavedGameMetadata meta)//this function is not called
{
if(status == SavedGameRequestStatus.Success)
{
// debugtext.text = "hello in save1";
if (issaving)//if is saving is true we are saving our data to cloud
{
debugtext.text = "Saving....";
byte[] data = System.Text.ASCIIEncoding.ASCII.GetBytes(GetDataToStoreinCloud());
SavedGameMetadataUpdate update = new SavedGameMetadataUpdate.Builder().Build();
((PlayGamesPlatform)Social.Active).SavedGame.CommitUpdate(meta, update, data, SaveUpdate);
}
else//if is saving is false we are opening our saved data from cloud
{
debugtext.text = "Loading...";
((PlayGamesPlatform)Social.Active).SavedGame.ReadBinaryData(meta, ReadDataFromCloud);
}
}
else{
debugtext.text = "Save request status broke";
}
}
What I checked twice before posting question:
Turned on Saved Games in google console
made build with your keystore and password
add email id in game service's tester section
Mistake is that you have to initialize save games from start as well and I didn't know that so answer would be
if (platform == null)
{
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().EnableSavedGames().Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.DebugLogEnabled = true;
platform = PlayGamesPlatform.Activate();
}
IEnumerator WWWLoader()
{
WWW bundleRequest = new WWW("*****************");
while(!bundleRequest.isDone)
{
yield return null;
}
AssetBundle bundle = null;
if (bundleRequest.bytesDownloaded > 0)
{
AssetBundleCreateRequest myRequest = AssetBundle.LoadFromMemoryAsync(bundleRequest.bytes);
while(!myRequest.isDone)
{
Debug.Log("loading....");
yield return null;
}
if (myRequest.assetBundle != null)
{
bundle = myRequest.assetBundle;
GameObject model = null;
if (bundle != null)
{
AssetBundleRequest newRequest = bundle.LoadAssetAsync<GameObject>("Log");
while (!newRequest.isDone)
{
Debug.Log("loading ASSET....");
yield return null;
}
model = (GameObject)newRequest.asset;
bundle.Unload(false);
}
}
else
{
Debug.LogError("COULDN'T DOWNLOAD ASSET BUNDLE FROM URL (assetBundle = null)");
}
}
else
{
Debug.LogError("COULDN'T DOWNLOAD ASSET BUNDLE FROM URL (0 bytes)");
}
}
This is my code to load an AssetBundle (I've removed the URL). It gives me the error "Failed to decompress data for the AssetBundle 'Memory'." I'm not sure if 'Memory' is referring to the AssetBundle name because mine is called 'log' so is it referring to a problem with memory? Any help on understanding this error and fixing it is much appreciated.
I believe your issue related to the compression being used when the bundles are built. You may need to use LoadFromMemoryAsync instead. https://docs.unity3d.com/ScriptReference/AssetBundle.LoadFromMemoryAsync.html
So, I have gotten past the error by using UnityWebRequestAssetBundle as shown here (recommended by derHugo).
I was initially using a simple FTP server to access the assets and it would not allow me to download them (from Unity, but in a browser it worked fine). I then switched to using a Flask server, which worked like a charm.
Note to people finding this like I did; if you're using Asset Bundles for webgl, you need to make sure the assetbundles are uncompressed (BuildAssetBundleOptions.UncompressedAssetBundle). Docs mention it but it can be easy to miss, and the default is LZMA.
I've developed a CI site on my local machine using WAMP. I'm using CI 3 with the HMVC extension and it all works fine.
I've just uploaded the site to the production server and changed the config files etc to get it working. However, form validation callbacks are not working on the production server.
Here's an example from a login form:
// Process login form
public function submit()
{
$this->load->library('form_validation');
$username = $this->input->post('username', TRUE);
$this->form_validation->set_rules('username', 'Username', 'required');
$this->form_validation->set_rules('password', 'Password', 'required|callback_do_login');
if($this->form_validation->run($this) == FALSE)
{
$this->login();
}
else
{
// Set login session
...
}
}
This is the callback function do_login:
public function do_login($password)
{
// Get user / pass from POST
$submitted_password = $this->input->post('password', TRUE);
$username = $this->input->post('username', TRUE);
$this->crud->setTable($this->table);
$this->load->model('mdl_users');
// Check User Exists
$query = $this->mdl_users->getUser($username);
if($query->num_rows() == 1)
{
// Get stored password
$row = $query->row();
$stored_password = $row->password;
// Check password
$this->load->module('mod_security');
$result = $this->mod_security->login($username, $submitted_password, $stored_password); // Returns false if no match
return ($result) ? TRUE : FALSE;
}
else
{
return FALSE;
}
}
On my local WAMP setup, this all works fine. But on the server
$this->form_validation->run($this)
always returns false.
To eliminate any errors with the callback function itself, I changed it to the following as a test:
public function do_login($password)
{
return TRUE;
}
... which will obviously always return TRUE, however when $this->form_validation->run($this) is called, even though I changed the do_login callback function to return TRUE, $this->form_validation->run($this) still returns FALSE!!
This is driving me crazy and I have no idea why this is happening. It is as if the form validation is ignoring the callback function and just returning false.
Can anyone help me? Could it be a setting on the server causing it or something else that could have changed when I uploaded the site files to the server?
If it is relevant, on my local machine, within the do_login callback function I had originally set the callback error message like this:
$this->form_validation->set_message('do_login', 'User / Pass Incorrect');
...which worked fine, but on the production server it threw an error stating: "Unable to access an error message corresponding to your field name Password.(do_login)". I had to set the error message in the language library file to overcome this. But the fact that this happened on the production server and not on my WAMP setup makes me think there must be some setting or something on the server that is causing this.
Anyway, any help is gratefully received.
Thanks
I finally found the solution. The HMVC application requires a small library file named as MY_Form_validation.php. Seemingly everywhere on the net this file is shown to be thus:
class MY_Form_validation extends CI_Form_validation {
function run($module = '', $group = '')
{
(is_object($module)) AND $this->CI = &$module;
return parent::run($group);
}
}
However, although this worked in my WAMP setup, it did not work on my server. I found that by declaring the CI variable at the start the server problem is resolved. So the MY_Form_validation.php file finally becomes:
class MY_Form_validation extends CI_Form_validation {
public $CI;
function run($module = '', $group = '')
{
(is_object($module)) AND $this->CI = &$module;
return parent::run($group);
}
}
Windows Azure Mobile Services currently doesn't have an option for custom authentication and looking at the feature request
http://feedback.azure.com/forums/216254-mobile-services/suggestions/3313778-custom-user-auth
It isn't coming anytime soon.
With a .NET backend and a .NET application how do you implement custom authentication, so that you don't have to use Facebook, Google or any of their other current providers?
There are plenty of partially completed tutorials on how this this is done with a JS backend and iOS and Android but where are the .NET examples?
I finally worked through the solution, with some help of the articles listed below, some intellisense and some trial and error.
How WAMS Works
First I wanted to describe what WAMS is in a very simple form as this part confused me for a while until it finally clicked. WAMS is just a collection of pre-existing technologies packaged up for rapid deployment. What you need to know for this scenario is:
As you can see WAMS is really just a container for a WebAPI and other things, which I won't go into detail here. When you create a new Mobile Service in Azure you get to download a project that contains the WebAPI. The example they use is the TodoItem, so you will see code for this scenario through the project.
Below is where you download this example from (I was just doing a Windows Phone 8 app)
I could go on further about this but this tutorial will get you started:
http://azure.microsoft.com/en-us/documentation/articles/mobile-services-dotnet-backend-windows-store-dotnet-get-started/
Setup WAMS Project
You will need your MasterKey and ApplicationKey. You can get them from the Azure Portal, clicking on your Mobile Services App and pressing Manage Keys at the bottom
The project you just downloaded, in the Controllers folder I just created a new controller called AccountController.cs and inside I put
public HttpResponseMessage GetLogin(String username, String password)
{
String masterKey = "[enter your master key here]";
bool isValidated = true;
if (isValidated)
return new HttpResponseMessage() { StatusCode = HttpStatusCode.OK, Content = new StringContent("{ 'UserId' : 'F907F58C-09FE-4F25-A26B-3248CD30F835', 'token' : '" + GetSecurityToken(new TimeSpan(1,0, 0), String.Empty, "F907F58C-09FE-4F25-A26B-3248CD30F835", masterKey) + "' }") };
else
return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Username and password are incorrect");
}
private static string GetSecurityToken(TimeSpan periodBeforeExpires, string aud, string userId, string masterKey)
{
var now = DateTime.UtcNow;
var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var payload = new
{
exp = (int)now.Add(periodBeforeExpires).Subtract(utc0).TotalSeconds,
iss = "urn:microsoft:windows-azure:zumo",
ver = 2,
aud = "urn:microsoft:windows-azure:zumo",
uid = userId
};
var keyBytes = Encoding.UTF8.GetBytes(masterKey + "JWTSig");
var segments = new List<string>();
//kid changed to a string
var header = new { alg = "HS256", typ = "JWT", kid = "0" };
byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header, Formatting.None));
byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload, Formatting.None));
segments.Add(Base64UrlEncode(headerBytes));
segments.Add(Base64UrlEncode(payloadBytes));
var stringToSign = string.Join(".", segments.ToArray());
var bytesToSign = Encoding.UTF8.GetBytes(stringToSign);
SHA256Managed hash = new SHA256Managed();
byte[] signingBytes = hash.ComputeHash(keyBytes);
var sha = new HMACSHA256(signingBytes);
byte[] signature = sha.ComputeHash(bytesToSign);
segments.Add(Base64UrlEncode(signature));
return string.Join(".", segments.ToArray());
}
// from JWT spec
private static string Base64UrlEncode(byte[] input)
{
var output = Convert.ToBase64String(input);
output = output.Split('=')[0]; // Remove any trailing '='s
output = output.Replace('+', '-'); // 62nd char of encoding
output = output.Replace('/', '_'); // 63rd char of encoding
return output;
}
You can replace what is in GetLogin, with your own validation code. Once validated, it will return a security token (JWT) that is needed.
If you are testing on you localhost, remember to go into your web.config file and fill in the following keys
<add key="MS_MasterKey" value="Overridden by portal settings" />
<add key="MS_ApplicationKey" value="Overridden by portal settings" />
You need to enter in your Master and Application Keys here. They will be overridden when you upload them but they need to be entered if you are running everything locally.
At the top of the TodoItemController add the AuthorizeLevel attribute as shown below
[AuthorizeLevel(AuthorizationLevel.User)]
public class TodoItemController : TableController<TodoItem>
You will need to modify most of the functions in your TodoItemController but here is an example of the Get All function.
public IQueryable<TodoItem> GetAllTodoItems()
{
var currentUser = User as ServiceUser;
Guid id = new Guid(currentUser.Id);
return Query().Where(todo => todo.UserId == id);
}
Just a side note I am using UserId as Guid (uniqueidentifier) and you need to add this to the todo model definition. You can make the UserId as any type you want, e.g. Int32
Windows Phone/Store App
Please note that this is just an example and you should clean the code up in your main application once you have it working.
On your Client App
Install NuGet Package: Windows Azure Mobile Services
Go into App.xaml.cs and add this to the top
public static MobileServiceClient MobileService = new MobileServiceClient(
"http://localhost:50527/",
"[enter application key here]"
);
In the MainPage.xaml.cs I created
public class Token
{
public Guid UserId { get; set; }
public String token { get; set; }
}
In the main class add an Authenticate function
private bool Authenticate(String username, String password)
{
HttpClient client = new HttpClient();
// Enter your own localhost settings here
client.BaseAddress = new Uri("http://localhost:50527/");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync(String.Format("api/Account/Login?username={0}&password={1}", username, password)).Result;
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
var token = Newtonsoft.Json.JsonConvert.DeserializeObject<Token>(response.Content.ReadAsStringAsync().Result);
App.MobileService.CurrentUser = new MobileServiceUser(token.UserId.ToString());
App.MobileService.CurrentUser.MobileServiceAuthenticationToken = token.token;
return true;
}
else
{
//Something has gone wrong, handle it here
return false;
}
}
Then in the Main_Loaded function
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
Authenticate("test", "test");
RefreshTodoItems();
}
If you have break points in the WebAPI, you will see it come in, get the token, then come back to the ToDoItemController and the currentUser will be filled with the UserId and token.
You will need to create your own login page as with this method you can't use the automatically created one with the other identity providers. However I much prefer creating my own login screen anyway.
Any other questions let me know in the comments and I will help if I can.
Security Note
Remember to use SSL.
References
[] http://www.thejoyofcode.com/Exploring_custom_identity_in_Mobile_Services_Day_12_.aspx
[] http://www.contentmaster.com/azure/creating-a-jwt-token-to-access-windows-azure-mobile-services/
[] http://chrisrisner.com/Custom-Authentication-with-Azure-Mobile-Services-and-LensRocket
This is exactly how you do it. This man needs 10 stars and a 5 crates of beer!
One thing, I used the mobile Service LoginResult for login like:
var token = Newtonsoft.Json.JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);
Hope to get this into Android now!
The task is to get the selected build configuration on the project's property page.
I have tried to achieve this by writing the following code:
private static IConfiguration getSelectedBuildConf(IProject proj) {
IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(proj);
if (info == null) {
return null;
} else {
IConfiguration cfg = info.getSelectedConfiguration();
return cfg;
}
}
The problem here is that getSelectedConfiguration() always returns null.
getSelectedConfiguration() returns always Debug configuration.
I think you want to use getDefaultConfiguration() instead of getSelectedConfiguration()...
As explained on cdt-dev list here.