webview whitelist urls possibly from external file - android-studio

We have locked down tablets deployed that are going to be using a webview based app that will allow our users to interact with our web app, website, and a few other whitelisted URL's like social media pages.
I know I can easily accept a single URL and reject all others with something like this:
public class MyWebViewClient extends WebViewClient {
public boolean shouldOverrideUrlLoading (WebView view, String url) {
if (Uri.parse(url).getHost().equals("http://Your_website_url")) {
// This is my web site, so do not override; let my WebView load the page
return false;
}
// reject anything other
return true;
}
}
mWebview.setWebViewClient(new MyWebViewClient()); //set the webviewClient
I could possibly adapt this to allow for multiple URL's but it seems somewhat messy and cumbersome. Ideally, I think an external XML file that can be updated without the app needing to be redeployed to all devices may be the way to go, I am a little unsure how to make that happen though and no one seems to have done this before that I can find.
I am fairly new to this so any help would be greatly appreciated.

Have your tablets reach back to a server for updated permission lists. You can look at Spring Cloud Config Server as a real-world example.

Related

Problems authenticating with MSAL and Azure B2C in a Xamarin.Forms app

I'm having some difficulty getting one of the sample Xamarin.Forms/Azure applications to work with my own Azure B2C tenant, specifically active-directory-b2c-xamarin-native.
I was able to get the sample to work out of the box, my only change being to update all the XF NuGet packages. At this point both the Android (on my Google Pixel) and UWP versions worked perfectly; on iOS I was able to log in/out and edit the profile (it still has the known issue that iPhoneSimulator doesn't properly save tokens in the keychain, so the API and caching doesn't work, but i'm ignoring that for now until i can get an actual iPhone). The problems started when I tried to set up and use my own B2C tenant, according to the instructions in the readme file. Since the original sample works, it's safe to assume that the code is ok; the only changes I made were to the magic strings at the top of App.cs, and the redirect URI's stored in AndroidManifest.xml and Info.plist. So the working theory is that I either entered one of those strings wrong, or the B2C setup is wrong. I've gone over this multiple times now and I can't find the issue. I'm willing to bet these are all caused by the same mistake on my part, though.
Problem 1 (solved). UWP app does not allow login. Instead when the embedded browser opens I get the message "We can't connect to the service you need right now. Check your network connection or try this again later", followed by an "MsalException: WAB authentication failed" dialog once I dismiss the browser.
This was the only issue I was able to fix so far, either by commenting out this line in the UWP.MainPage constructor:
UserDetailsClient.Core.App.PCA.RedirectUri = WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();
or by adding the value returned by that GetCurrentApplicationCallbackUri() call (which is something like "ms-app://s-1-15-2-900855338....") to the Custom Redirect URI list of the UI app in B2C. I would prefer simply removing the line of code, but that begs the question as to why that line of code was needed in the first place. Perhaps someone can suggest why using the ms-app:// redirect on the backend might be preferable to the msalXXXX://auth used by the other platforms. I have no idea why the original sample worked with the ms-app:// redirect; perhaps that string is actually constant across all apps and is already defined in the sample's B2C tenant.
Problem 2. Having gotten past the UWP login issue now everything works on that platform EXCEPT for the API call. I get a 401 Unauthorized.
The API code is taken straight from the tutorial Develop Cloud Connected Mobile Apps with Xamarin and Microsoft Azure; it's just the backend from Chapter 1, with the [Authorize] attribute added to the TodoItemController. (All of the Chapter 1 code works, btw) App Service Authentication is still turned off on the API itself (not the B2C tenant) in Azure. If I remove the Authorize attribute from the TodoItemController, it works, provided I also pass in the additional header ZUMO-API-VERSION=2.0.0. Adding the header does not help with the 401, though.
Since I'm able to login, I'm guessing I have a valid access token, it's just not what the backend is expecting. Again, this works on the sample, so I don't know how my app differs. I suspect this issue also affects iOS and Android, but I'm not sure because unable to complete the login on those platforms. Which brings me to...
Problem 3. On Android & iOS, on clicking SIGN IN the app opens the system browser and I'm able to login in, but the subsequent redirect doesn't happen and the app remains in it's initial state. When debugging, the line after the call to App.PCA.AcquireTokenAsync() is never reached. No exception is raised.
From what I understand this is generally due to either the redirect URI being improperly formed or forgetting to add the platform-specific redirect code (intent-filter on Android, or OpenUrl on iOS). I've double-checked the URI a half-dozen times, and the code has to be correct since the sample worked. I did notice the ActivityManager START entry in the Android logcat, so the browser is sending the redirect, but the app isn't responding to it for whatever reason. Note also that the UWP client DOES work using that same msalXXXX://auth URI (this is why I bothered to explain problem 1 above)
Visual Studio 2017 15.8.6
Xamarin.Forms 3.2.0.871581
Microsoft.Identity.Client 1.1.4-preview
Below is the list of strings from App.cs, as well as screenshots from my B2C setup. Any help would be greatly appreciated!
public static string Tenant = "myapp.onmicrosoft.com";
public static string ClientID = "d43c8xxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
public static string PolicySignUpSignIn = "B2C_1_emailPolicy";
public static string PolicyEditProfile = "B2C_1_profileEditPolicy";
public static string PolicyResetPassword = "B2C_1_passwordResetPolicy";
public static string[] Scopes = { "https://myapp.onmicrosoft.com/api/read" };
public static string ApiEndpoint = "https://myapp.azurewebsites.net/tables/todoItem";
public static string AuthorityBase = $"https://login.microsoftonline.com/tfp/{Tenant}/";
public static string Authority = $"{AuthorityBase}{PolicySignUpSignIn}";
public static string AuthorityEditProfile = $"{AuthorityBase}{PolicyEditProfile}";
public static string AuthorityPasswordReset = $"{AuthorityBase}{PolicyResetPassword}";

files in server root not loading properly in Azure

I'm working on an app that instead of a database uses file system in the server's root directory. It's basically a note application that allows me to save notes. Each note is a serialized object of Note class represented by following structure \Data\Notes\MyUsername\Title.txt
When I'm testing this on localhost through IIS Express everything works fine and I can easily go step by step there.
However, once I publish the app to Azure, the folder structure is still there (made a test Controller that uses Directory.GetFiles() and .GetDirectories() to simulate folder browsing so I'm sure that the files are there) but the file simply doesn't get loaded.
Loading script that's being called:
public T Load<T>(string filePath) where T : new()
{
StreamReader reader = null;
try
{
reader = new StreamReader(filePath);
var RawDB = reader.ReadToEnd();
return JsonConvert.DeserializeObject<T>(RawDB);
}
catch
{
return default(T);
}
finally
{
if (reader != null)
reader.Dispose();
}
}
Since I can't normally debug the app on Azure I tried to dump as much info as I can through ViewData and even there, everything looks okay and the paths match, but the deserialized object is still null, and this is only when trying to open an existing note WITHOUT creating a new one first (more on that later)
Additionally, like I said, those new notes get saved in the folder structure, and there's a Note sidebar on the left that allows users to switch between notes. The note browser is nothing more but a list that's collected with a .GetFiles() of that folder.
On Azure, this works normally and if I were to delete one manually it'd be removed from the sidebar as well.
Now here's the kicker. On localhost, adding a note adds it to the sidebar and I can switch between them normally.
Adding a note on Azure makes all Views only display that new note regardless of which note I open and the new note does NOT get stored in the structure (I don't know where it ended up at all!) even though the path is defined at that point normally and it should save just like it does on localhost.
var model = new ViewNoteModel()
{
Note = Load<Note>($#"{NotePath}\{Title}.txt"), //Works on localhost, fails on Azure on many levels. Title is a URL param.
MyNotes = GetMyNotes() //works fine, reads right directory on local and Azure
};
To summarize:
Everything works fine on localhost, Important part doesn't work on Azure.
If new note is not created but an existing note is opened, Correct note gets loaded (based on URL Param) on Localhost, it breaks on Azure and loads default Note object (not null, just the default constructor data since it's required by JsonConvert)
If a new note is created, you'll see it on Localhost and you'll be able to open all other notes regardless, you will see only the new note on Azure regardless of note picked.
It's really strange and I have no idea what could cause this? I thought it had something to do with Azure requests being handled differently so maybe controller pushes the View before the model is initialized completely but that doesn't make sense since there's nothing async here.
However the fact that it loads a note that doesn't exist on the server it's even more apsurd and I have no explanation for that.
Additionally this issue is not linked with a session. I logged in through my phone and it showed the fake note there as well right away.
P.S. Before you say anything about storage, please note this. Our university grants us a very limited Azure subscription. Simple lowest tier App service and 5DTU SQL server and 99% of the rest is locked out of our subscription. This is why I'm storing stuff on the server, not because I believe it's the smart thing to do.

Web api routing only permits one controller

I created a new Web API project and created the following routing spec (actually I have simplified, looking for the bug):
// Web API configuration and services
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}"
);
When I make a call via ajax with the route:
/api/account/GetSUID/0
everything works fine. When I just use a different controller:
/api/tile/GetTileSet/0
it returns a status of 200 but instead of hitting my controller, it just returns the contents of the default page in jqXHR.responseText! It is as if it is just skipping any API routing like I am requesting the default site page.
I am baffled by this one as I have written literally hundreds of web API functions over the past few years in several other projects. I have never had any issue making calls to multiple controllers. I have looked high and low for what could be happening here and am hoping that someone here might have an idea.
Here is a sample method on the controller:
[HttpGet]
public HttpResponseMessage CheckRequestedID(int id, [FromUri]string Search)
{
if (!BSDIUtil.HasAllAcceptableCharacters(Search))
return Request.CreateResponse(HttpStatusCode.BadRequest);
if (FolderModel.IDAlreadyExists(DAL, Search)) // We can check this because this function is only called when staff members are creating accounts for other people (participants always use their email).
return Request.CreateResponse(HttpStatusCode.OK, false);
else
return Request.CreateResponse(HttpStatusCode.OK, true);
}
This will work if on the account controller but not on the tile controller.
One other thing, I am using the "Community" edition of Visual Studio and Windows 8.1
This is not a problem that is likely to occur often but I have solved it and figured I would post it here in case anyone else has the same issue.
I am using web api in the context of a standard web forms app (although I am only using webforms for my reporting pages). In the web.config for a web forms app, you can declare the paths that the user has access to before authenticating. I was only providing access to the account controller: all others were not permitted due to my authentication mechanism. Once I authenticate (e.g. the forms authentication call) or if I change the location path to include only "api", the problem goes away.
I was facing same problem but in different context. Had many controllers and respective routing templates. Only one controller was responding to requests.
Later i realized my other controller classes were not public!!

Render mobile version of login in Secure class Play! Framework

Is it possible to somehow override the login method of the Secure.java class of the Secure-Module in Play! Framework, so that another version of the login form is displayed?
In my case, i want to display a mobile version of the login-form if a mobile browser is detected.
I know i should not change the Secure.java class itself, but i don't really see any other solution to this problem.
As discussed in other posts you have the request in your Play! controller. So in this request you could ask which agent is trying to view your website:
String agentInfo = request.headers.get("user-agent");
The you can determine which template will be rendered for this agent:
if (agentType.isWhatEverHeIs) {
renderTemplate("Application\mobileTemplateForBadPractise.html");
} else {
render();
}
But what I would encourage you to do is responsive webdevelopment. Create your templates as smart as possible, let the template and css and javascript do this and keep your business logic in your controller.
You could use the Twitter Bootstrap to achieve this, but there are many more! Like Skeleton.
You even got the request object inside your templates so that you can optionally render things in your template (or not) based on the agent.
Even simpler, simply create/override the secure/login.html template and use responsive design : media queries. No need to change the controller or check agent or whatever.

Best practice for SharePoint vanity url/redirection

My employer uses MOSS 2007 for our company intranet. It runs solely on secure http and is also exposed to the outside world via ISA. I currently have a request to add a forwarding URL to our site so that something like the following will occur:
intranet.mycompany.com/vanityname
redirects to ->
intranet.mycompany.com/somedeeplink/default.aspx
I fully expect this sort of thing will become more popular with our users as time goes on. So I am looking for a solution that scales. I have read various articles about creating a /site/ with forwarding meta tags or a forwarding SharePoint page type. I've also seen some that talk about adding virtual directories, etc directly in IIS. All these solutions seem to be overkill and inevitably take up more memory or processing time on the web servers.
I am currently leaning towards writing an http module that can be configured in the web.config and perform redirects. I wanted to get feedback to see if anyone else has done something similar in SharePoint 2007 and had any suggestions. Again, I'd like to implement something that scales without making major changes later on and is going to put minimal processing burden on our web servers. Thanks!
Ive implemented url redirecting with MOSS using the HTTP module route. I documented the code I used and what parameters worked the best for me here;
http://scaredpanda.com/2008/08/url-rewriting-with-sharepoint-moss-2007/
Take a look and let me know if this helps you and if you have any questions.
Update: The link above is no longer valid, so here text from the page that I used for URL redirect.
After messing around for a little bit it, I came up with a good way to do it. When I was looking for examples on the web there were a lot of people saying that it couldnt be done. But in the end it actually didn’t take much to implement it. Here’s an HttpModule that I wrote to do the work.
The key pieces are the this.app.BeginRequest += new EventHandler(app_BeginRequest) which
steps in front of the request and allows the module to get its redirect on.
And HttpContext.Current.RewritePath(redirect, false); will push the necessary headers n such forward so that the receiving .aspx page will understand how to correctly post back.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;
using System.Collections;
using System.Text;
using System.Web;
using System.Web.Caching;
using System.Web.SessionState;
using System.Security.Cryptography;
using System.Configuration;
using System.Threading;
using System.IO;
using System.Security;
using System.Security.Principal;
namespace ScaredPanda
{
public sealed class RewriteHttpModule : IHttpModule
{
HttpApplication app = null;
///
/// Initializes the httpmodule
///
public void Init(HttpApplication httpapp)
{
this.app = httpapp;
this.app.BeginRequest += new EventHandler(app_BeginRequest);
}
public void app_BeginRequest(Object s, EventArgs e)
{
try
{
//determine if the income request is a url that we wish to rewrite.
//in this case we are looking for an extension-less request
string url = HttpContext.Current.Request.RawUrl.Trim();
if (url != string.Empty
&& url != "/"
&& !url.EndsWith("/pages")
&& !url.Contains(".aspx")
&& url.IndexOf("/", 1) == -1)
{
//this will build out the the new url that the user is redirected
//to ie pandas.aspx?pandaID=123
string redirect = ReturnRedirectUrl(url.Replace("/", ""));
//if you do a HttpContext.Current.RewritePath without the 'false' parameter,
//the receiving sharepoint page will not handle post backs correctly
//this is extremely useful in situations where users/admins will be doing a
//'site actions' event
HttpContext.Current.RewritePath(redirect, false);
}
}
catch (Exception ex)
{
//rubbish
}
}
}
}
Have you looked into Alternate Access Mappings?
http://technet.microsoft.com/en-us/library/cc263208.aspx
If you are open to paying for a solution. Have a look:
NOT FREE -> http://www.muhimbi.com/Products/SharePoint-URL-Shortener.aspx
Depending on the number of redirects you might want to implement an HTTP module as stated) but how about checking out
FREE -> http://www.codeplex.com/sharepointsmart404
Use the URL Rewrite feature in IIS. (I believe it's an IIS 7 extension)
http://www.iis.net/download/urlrewrite

Resources