OpenID OWIN auth and lack of user permissions - azure

I may be handling this totally incorrect, but I am using OpenID with MS Azure to authentication my users, then I check to make sure the user has a user account in the notifications of the OpenID middleware, if the user is not found, I am throwing a security exception. How do I return a You do not have access to this applicaiton type page. Am I just missing the hook?
Here is the example:
https://gist.github.com/phillipsj/3200ddda158eddac74ca

You can use try...catch inside the notifications, something along these lines:
SecurityTokenValidated = (context) =>
{
try
{
// retriever caller data from the incoming principal
var username = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value.Split('#')[0];
var database = DependencyResolver.Current.GetService(typeof (IDatabase)) as IDatabase;
var employee = database.Query(new GetEmployeeByUsername(username));
if (employee == null)
{
throw new SecurityTokenValidationException();
}
// I add my custom claims here
context.AuthenticationTicket.Identity.AddClaims(claims);
return Task.FromResult(0);
}
catch (SecurityTokenValidationException ex)
{
context.HandleResponse(); // This will skip executing rest of the code in the middleware
context.Response.Redirect(....);
return Task.FromResult(0);
}
}

Related

Azure AD B2C Integrating with Restful API

So, I followed the walkthrough as specified here.
Here is the flow:
The user enters username/password on the SigInSignUp Policy page (provided by Azure AD B2C) and is redirected to the ASP.NET Web API which I wrote to check some business logic.
At this point, I would like to redirect to different URLs based on the flags that I return as part of output claim. How can I achieve that?
I would like to redirect to different URLs based on the flags that I return as part of output claim.
register for OnTicketReceived
builder.AddOpenIdConnect(options => {
options.Events = new OpenIdConnectEvents {OnTicketReceived = OnTicketReceived };
});
Use the event handler to do something to the response, like redirect, or set a flag to be read later.
private Task OnTicketReceived(TicketReceivedContext context)
{
// set a flag for later. Maybe middleware?
context.HttpContext.Items["DoSomething"] = true;
// Or just handle the response completely
if(context.Principal.HasClaim(claim => ...predicate about the claim... ))
{
context.Response.Clear();
context.Response.Headers.Add("Location", "http://wherever.you.want.com");
// tell the OpenIdConnect middleware we got this
context.HandleResponse();
}
Debug.WriteLine(nameof(OnTicketReceived));
//context.Principal = TransformClaims(context, context.Principal);
return Task.CompletedTask;
}

External Login WebAPI2 MVC5

I need to use a 3rd party token as a way to authenticate. I'm getting the token in the home controller and need to be able to send it on to my WebAPI controllers (It's an SPA application using Backbone). Is there a way of doing this?
EDIT:
Relevant code:
public ActionResult Index(string projectId, int companyId, bool isCompanyAdmin)
{
// if not a valid user return error
var validate = new Validate().ValidateContext(HttpContext,
"Key", "Secret");
if (!validate.IsValidated) return View(Constants.ValidationFailed);
// The info validated, so now I can set it to authorized
// put code here for doing it
//Get the model for the user
try
{
var model = ConvertToVM(_smsRepository.GetCompany(companyId, projectId));
}
catch (ProviderIncompatibleException)
{
// connection string wrong
return View(Constants.ConnectionFailed);
}
catch (Exception e)
{
// catch all
return View(Constants.DatabaseError);
}
//create and send through the view model that determines what view the user will get
return View(model);
}
Ok I put in the index method on the Home Controller. Like I said, we make a call to a third party API passing in the context, the client key, and the client secret to verify our identity. Could I just add a Bearer token in the home controller? Or otherwise pass the http context to OWiN and use some custom logic to add the token if validate.IsValidated is true? It needs to be something that works with WebAPI.

Azure App Services (Mobile Apps) AAD authentication token refresh

I am trying to use Azure Active Directory to perform login functions on my uwp app. This happens successfully however I cannot get it to refresh the token when it expires and always receive the error "Refresh failed with a 403 Forbidden error. The refresh token was revoked or expired." and so I have to bring up the login window again. I am using the version 2.1.0 and the following code to authenticate:
private async Task<bool> AuthenticateAsync(bool forceRelogon = false)
{
//string message;
bool success = false;
// Use the PasswordVault to securely store and access credentials.
PasswordVault vault = new PasswordVault();
PasswordCredential credential = null;
//Set the Auth provider
MobileServiceAuthenticationProvider provider = MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory;
MobileServiceUser user = null;
try
{
// Try to get an existing credential from the vault.
var credentials = vault.FindAllByResource(provider.ToString());
credential = credentials.FirstOrDefault();
}
catch (Exception ex)
{
// When there is no matching resource an error occurs, which we ignore.
Debug.WriteLine(ex);
}
if (credential != null && !forceRelogon)
{
// Create a user from the stored credentials.
user = new MobileServiceUser(credential.UserName);
credential.RetrievePassword();
user.MobileServiceAuthenticationToken = credential.Password;
// Set the user from the stored credentials.
App.MobileService.CurrentUser = user;
//message = string.Format($"Cached credentials for user - {user.UserId}");
// Consider adding a check to determine if the token is
// expired, as shown in this post: http://aka.ms/jww5vp.
if (RedemptionApp.ExtensionMethods.TokenExtension.IsTokenExpired(App.MobileService))
{
try
{
await App.MobileService.RefreshUserAsync();
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
success = true;
}
else
{
try
{
// Login with the identity provider.
user = await App.MobileService
.LoginAsync(provider);
// Create and store the user credentials.
if (credential != null)
vault.Remove(credential);
credential = new PasswordCredential(provider.ToString(),
user.UserId, user.MobileServiceAuthenticationToken);
vault.Add(credential);
success = true;
//message = string.Format($"You are now logged in - {user.UserId}");
}
catch (MobileServiceInvalidOperationException)
{
//message = "You must log in. Login Required";
}
}
//var dialog = new MessageDialog(message);
//dialog.Commands.Add(new UICommand("OK"));
//await dialog.ShowAsync();
return success;
}
Can anyone see something wrong with what I am doing, or need to do anything within the AAD service provider?
You might be able to get more accurate information by taking a look at the server-side application logs. Token refresh failure details will be logged there automatically. More details on application logs can be found here: https://azure.microsoft.com/en-us/documentation/articles/web-sites-enable-diagnostic-log/. I recommend setting the trace level to Informational or Verbose.
Also, if you haven't done this already, Azure AD requires a bit of extra configuration to enable refresh tokens. Specifically, you need to configure a "client secret" and enable the OpenID Connect hybrid flow. More details can be found in this blog post: https://cgillum.tech/2016/03/07/app-service-token-store/ (scroll down to the Refreshing Tokens section and see where it describes the process for AAD).
Besides what has been said about mobile app configuration, I can spot this.
You have:
// Login with the identity provider.
user = await App.MobileService.LoginAsync(provider);
It should be:
user = await App.MobileService.LoginAsync(MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory,
new Dictionary<string, string>() {{ "response_type", "code id_token" }});
Maybe this will help:
https://azure.microsoft.com/en-us/blog/mobile-apps-easy-authentication-refresh-token-support/

Auth0 access control

I am using Auth0 to manage a large set of users across several different applications with some being web based and others desktop and mobile. Under the meta data for each user I have an array of applications each user can access, I wondered how I might check this when authenticating so that access would be refused if not within that list.
I can do this very easily on the applications, however it would be great to do it on Auth0.
Using a Rule defined as follows has provided me with the functionality I was looking for:
function (user, context, callback) {
// ACL object
var acl = {
"someAppName": [ 'user1#mail.com', 'user2#mail.com' ],
"otherApp": ['user2#mail.com']
}
// if App is not in the ACL, skip
if(!acl.hasOwnProperty(context.clientName)){
return callback(null, user, context);
}
// check if user has access to app
var userHasAccess = acl[context.clientName].some(
function (email) {
return email === user.email;
}
);
if (!userHasAccess) {
return callback(new UnauthorizedError('Access denied.'));
}
callback(null, user, context);
}

No application keys for Azure Mobile Apps - what's a simple replacement?

I've been using Azure Mobile Services and now I created one of the new Mobile Apps via the all new Azure Portal.
While using Mobile Services it was possible to limit API access via an application key. The concept of this key no longer applies to Mobile Apps it seems.
All I need is a really lightweight protection of my services, exactly what the Application Key did. I just want to prevent that everybody out there navigates to my Azure app and messes around with my database; the App Key was perfect for those cases when you did not have anything to hide but wanted to prevent "spamming".
I see there is now Active Directory integration as an alternative but unfortunately I cannot find a guide how to move from App Key to something else.
Check this post How to configure your App Service application to use Azure Active Directory login
this authentication sample code works with UWP
private async Task AuthenticateAsync()
{
while (user == null)
{
string message=string.Empty;
var provider = "AAD";
PasswordVault vault=new PasswordVault();
PasswordCredential credential = null;
try
{
credential = vault.FindAllByResource(provider).FirstOrDefault();
}
catch (Exception)
{
//Ignore exception
}
if (credential != null)
{
// Create user
user = new MobileServiceUser(credential.UserName);
credential.RetrievePassword();
user.MobileServiceAuthenticationToken = credential.Password;
// Add user
App.MobileServiceClient.CurrentUser = user;
try
{
//intentamos obtener un elemento para determinar si nuestro cache ha experidado
await App.MobileServiceClient.GetTable<Person>().Take(1).ToListAsync();
}
catch (MobileServiceInvalidOperationException ex)
{
if (ex.Response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
//remove expired token
vault.Remove(credential);
credential = null;
continue;
}
}
}
else
{
try
{
//Login
user = await App.MobileServiceClient
.LoginAsync(provider);
//Create and store credentials
credential = new PasswordCredential(provider,
user.UserId, user.MobileServiceAuthenticationToken);
vault.Add(credential);
}
catch (MobileServiceInvalidOperationException ex)
{
message = "You must log in. Login Required";
}
}
message = string.Format("You are now logged in - {0}", user.UserId);
var dialog = new MessageDialog(message);
dialog.Commands.Add(new UICommand("OK"));
await dialog.ShowAsync();
}
}

Resources