I've been working on how to save OpenIdConnecConfiguration locally in the odd case that the AuthServer is not reachable but the frontend client (e.g. Phone) still has a valid refresh token which still needs to be validated again when signing in. It is also needed to be saved locally to a file in the case that the backend (e.g. WCF) has restarted due to a update or the frequent restarts it has (once a day)
What I've done so far, I've saved the JSON object of the ".well-known/openid-configuration" to a file/variable and now I want to create the OpenIdConnectConfiguration object.
OpenIdConnectConfiguration.Create(json) does a lot of the work but the signingKeys do not get created. I think maybe it's because the authorization endpoint needs to be created in some other manner maybe?
Or maybe I'm doing this the wrong way and there is another solution to this issue. I'm working in C#.
Edit: I know there are some caveats to what I'm doing. I need to check once in awhile to see if the public key has been changed, but security wise it should be fine to save the configuration because it's already public. I only need the public key to validate/sign the jwt I get from the user and nothing more.
Figured out a solution after looking through OpenIdConnectConfiguration.cs on the official github.
When fetching the OpenIdConnectConfiguration the first time, use Write() to get a JSON string and use it to save it to file.
Afterwards when loading the file, use Create() to create the OpenIdConnectConfiguration again from the JSON string (This had the issue of not saving the signingKeys as said in the question, but alas! there is a fix)
Lastly to fix the issue with the signingKeys not being created, (this is what I found out from the github class) all we need to do is loop through the JsonWebKeySet and create them as is done in the class. We already have all the information needed from the initial load and therefore only need to create them again.
I'll leave the code example below of what I did. I still need to handle checking if he key has been changed/expired which is the next step I'll be tackling.
interface IValidationPersistence
{
void SaveOpenIdConnectConfiguration(OpenIdConnectConfiguration openIdConfig);
OpenIdConnectConfiguration LoadOpenIdConnectionConfiguration();
}
class ValidationPersistence : IValidationPersistence
{
private readonly string _windowsTempPath = Path.GetTempPath();
private readonly string _fileName = "TestFileName";
private readonly string _fullFilePath;
public ValidationPersistence()
{
_fullFilePath = _windowsTempPath + _fileName;
}
public OpenIdConnectConfiguration LoadOpenIdConnectionConfiguration()
{
FileService fileService = new FileService();
OpenIdConnectConfiguration openIdConfig = OpenIdConnectConfiguration.Create(fileService.LoadFromJSONFile<string>(_fullFilePath));
foreach (SecurityKey key in openIdConfig.JsonWebKeySet.GetSigningKeys())
{
openIdConfig.SigningKeys.Add(key);
}
return openIdConfig;
}
public void SaveOpenIdConnectConfiguration(OpenIdConnectConfiguration openIdConfig)
{
FileService fileService = new FileService();
fileService.WriteToJSONFile(OpenIdConnectConfiguration.Write(openIdConfig), _fullFilePath);
}
}
Related
Given I executed some steps, then on certain step I get a value from a database cell. Since this value is unknown prior to execution, I cannot use any binding or table value defined in feature file, is there any way to populate this value into Step Definition => then it is showed on other report?
For ex a feature file:
Given I drop the file to the server's UNC path
When the file is processed successfully
Then a new account is loaded as (.*) (this is the number generated at runtime)
The account can only be know at the last step through a connection to the database, is there any way to put it to the step definition so that later it shows as:
The a new account is loaded as 100051359
What you want to do is not possible with SpecFlow. However, you can still get a good test out of this, but you will likely need to share data between steps using the ScenarioContext.
The step that processes the file will need to know the newly loaded account Id. Then that step can put that account Id in the ScenarioContext:
[Binding]
public class FileSteps
{
private readonly ScenarioContext scenario;
public FileSteps(ScenarioContext scenario)
{
this.scenario = scenario;
}
[When(#"the file is processed successfully"]
public void WhenTheFileIsProcessedSuccessfully()
{
var account = // process the file
scenario.Set(account.Id, "AccountId");
}
}
Later when making the assertion, get the account Id from the scenario context before making your assertion:
[Binding]
public class AccountSteps
{
private readonly ScenarioContext scenario;
public AccountSteps(ScenarioContext scenario)
{
this.scenario = scenario;
}
[Then(#"a new account is loaded")]
public void ThenANewAccountIsLoaded()
{
var account = accountRepository.Find(scenario.Get<int>("AccountId"));
// Assert something about the account
}
}
And your test becomes:
Scenario: ...
Given I drop the file to the server's UNC path
When the file is processed successfully
Then a new account is loaded
I'm trying to get the edit URL of a content as a string from backend, the catch is I'm inside a workflow activity, so I can't use Url.Action... or Url.ItemEditLink... or other UrlHelpers as if it were a controller or a view. Also, although I'm inside a workflow, the contents I need it for are not part of the workflowContext or the activityContext, so I can't use those or tokens either.
A solution could be to get the content metadata and the site baseUrl and try to build it manually, but I think this way is prone to errors.
Thanks.
This is how I build a Uri in an activity:
public class MyClass : Task
{
private readonly RequestContext _requestContext;
...
public MyActivity(RequestContext requestContext, ...)
{
_requestContext = requestContext;
...
}
...
public override IEnumerable<LocalizedString> Execute(WorkflowContext workflowContext, ActivityContext activityContext)
{
var content = ... get using ID
var helper = new UrlHelper(_requestContext);
var baseurl = new Uri(_orchardServices.WorkContext.CurrentSite.BaseUrl);
Uri completeurl = new Uri(baseurl, helper.ItemDisplayUrl(content));
yield return T("Done");
}
}
Turns out that I actually do build the Uri semi-manually, but I haven't had issues with this method. You may be able to use just the ItemDisplayUrl for navigation inside of Orchard; I had to get the full URL because the string gets sent to an outside program (Slack).
Say for example I have a something like this declared in Starcounter
[Database]
public class User
{
public string Username;
public string Email;
}
I have a page listing one row from the DB with an update button with PuppetJS and all working fine.
If I change the value from another session or directly in the DB, is there anyway to directly update the values to any client who are active by pushing the new values to the clients?
*** Edit:
I added following to my TestPage.json.cs file :
void Handle(Input.Update action)
{
Transaction.Commit();
Session.ForAll(s =>
{
if (s.Data is TestPage)
s.CalculatePatchAndPushOnWebSocket();
});
}
This push updates directly to other sessions nicely. Still wonder if there is some better way to do this.
The code that you've presented in your edit is exactly the way to go:
void Handle(Input.Update action)
{
Transaction.Commit();
Session.ForAll(s =>
{
if (s.Data is TestPage)
s.CalculatePatchAndPushOnWebSocket();
});
}
What it does is:
commit changes to db
for every running session, check if that session has a TestPage instance attached to it
if the above is positive, revaluate the bound data and send patches if required
More about pushing changes over WebSocket can be found here: http://starcounter.io/guides/web/sessions/.
I have a business requirement to only send permissioned properties in our response payload. For instance, our response DTO may have several properties, and one of them is SSN. If the user doesn't have permissions to view the SSN then I would never want it to be in the Json response. The second requirement is that we send null values if the client has permissions to view or change the property. Because of the second requirement setting the properties that the user cannot view to null will not work. I have to still return null values.
I have a solution that will work. I create an expandoObject by reflecting through my DTO and add only the properties that I need. This is working in my tests.
I have looked at implementing ITextSerializer. I could use that and wrap my response DTO in another object that would have a list of properties to skip. Then I could roll my own SerializeToString() and SerializeToStream(). I don't really see any other ways at this point. I can't use the JsConfig and make a SerializeFn because the properties to skip would change with each request.
So I think that implementing ITextSerializer is a good option. Are there any good examples of this getting implemented? I would really like to use all the hard work that was already done in the serializer and take advantage of the great performance. I think that in an ideal world I would just need to add a check in the WriteType.WriteProperties() to look and the property is one to write, but that is internal and really, most of them are so I can't really take advantage of them.
If someone has some insight please let me know! Maybe I am making the implementation of ITextSerialzer a lot harder that it really is?
Thanks!
Pull request #359 added the property "ExcludePropertyReference" to the JsConfig and the JsConfigScope. You can now exclude references in scope like I needed to.
I would be hesitant to write my own Serializer. I would try to find solutions that you can plug in into the existing ServiceStack code. That way you will have to worry less about updating dlls and breaking changes.
One potential solution would be decorating your properties with a Custom Attributes that you could reflect upon and obscure the property values. This could be done in the Service before Serialization even happens. This would still include values that they user does not have permission to see but I would argue that if you null those properties out they won't even be serialized by JSON anyways. If you keep all the properties the same they you will keep the benefits of strong typed DTOs.
Here is some hacky code I quickly came up with to demonstrate this. I would move this into a plugin and make the reflection faster with some sort of property caching but I think you will get the idea.
Hit the url twice using the following routes to see it in action.
/test?role
/test?role=Admin (hack to pretend to be an authenticated request)
[System.AttributeUsage(System.AttributeTargets.Property)]
public class SecureProperty : System.Attribute
{
public string Role {get;set;}
public SecureProperty(string role)
{
Role = role;
}
}
[Route("/test")]
public class Test : IReturn
{
public string Name { get; set; }
[SecureProperty("Admin")]
public string SSN { get; set; }
public string SSN2 { get; set; }
public string Role {get;set;}
}
public class TestService : Service
{
public object Get(Test request)
{
// hack to demo roles.
var usersCurrentRole = request.Role;
var props = typeof(Test).GetProperties()
.Where(
prop => ((SecureProperty[])prop
.GetCustomAttributes(typeof(SecureProperty), false))
.Any(att => att.Role != usersCurrentRole)
);
var t = new Test() {
Name = "Joe",
SSN = "123-45-6789",
SSN2 = "123-45-6789" };
foreach(var p in props) {
p.SetValue(t, "xxx-xx-xxxx", null);
}
return t;
}
}
Require().StartHost("http://localhost:8080/",
configurationBuilder: host => { });
I create this demo in ScriptCS. Check it out.
I am developing a BlackBerry App and saving a lot of values as String and boolean to the Persistent Store. I am aware of the fact that String and boolean values do not get deleted from Persistent when an App is deleted/uninstalled from the handset. I am also aware of the fact that in order to delete these values I need to store this in a "project" specific class. I have been struggling with it and so would want a temporary work around. I am saving a boolean value in order to determine which screen the App should load it.
PersistentStoreHelper.persistentHashtable.put("flagged",Boolean.TRUE);
if (PersistentStoreHelper.persistentHashtable.containsKey("flagged"))
{
boolean booleanVal = ((Boolean) PersistentStoreHelper.persistentHashtable.get("flagged")).booleanValue();
if (booleanVal==true)
{
pushScreen(new MyScreen());
}
}
else
{
pushScreen(new MyScreen(false));
}
Is it possible to store this boolean value as an Object so that it gets deleted when the App is uninstalled/deleted. Please help as well as comment if I am missing out on anything.
Once again, I'd recommend you change your PersistentStoreHelper to this version online.
You certainly can get Boolean and String values to be deleted from the persistent store when your app is uninstalled, but they need to be inside an object that can only exist in your app.
For example:
PersistentStoreHelper store = PersistentStoreHelper.getInstance();
store.put("flagged", Boolean.TRUE);
// commit will save changes to the `flagged` variable
store.commit();
and then retrieve it later with:
PersistentStoreHelper store = PersistentStoreHelper.getInstance();
boolean isFlagged = ((Boolean)store.get("flagged")).booleanValue();
The key that makes this work is inside my PersistentStoreHelper class, it saves everything inside a subclass of Hashtable that's unique to my/your app (MyAppsHashtable). You need to store your String or Boolean objects inside that app-unique Hashtable subclass, not in a normal java.util.Hashtable.
Again, please make this easy on yourself, and use the code I posted.
Note: also, you probably know this, but you may need to reboot your device to see the app, and its persistent store data, fully deleted.
Update
If you had changed the original PersistentStoreHelper class that I had posted online, because you wanted access to the containsKey() method, or other methods in the Hashtable class, you can solve that problem by simply adding code like this:
public boolean containsKey(String key) {
return persistentHashtable.containsKey(key);
}
to the PeristentStoreHelper class. Please don't make persistentHashtable a public static member. As you need to use more Hashtable methods, just add wrappers for them, like I show above with containsKey(). Of course, you can achieve the same thing as containsKey() by simply using this code:
boolean containsFlagged = (store.get("flagged") != null);
Update 2
If you get stuck with old persistent data, that you need to clean out, you can modify PersistentStoreHelper to detect and correct the situation, like this (hattip to #adwiv for suggestions):
private PersistentStoreHelper() {
persistentObject = PersistentStore.getPersistentObject(KEY);
Object contents = persistentObject.getContents();
if (contents instanceof MyAppsHashtable) {
persistentHashtable = (MyAppsHashtable)contents;
} else {
// store might be empty, or contents could be the wrong type
persistentHashtable = new MyAppsHashtable();
persistentObject.setContents(persistentHashtable);
persistentObject.commit();
}
}