I have a two slots for mobile app service at Azure: production and development. Also I have a client app that can work with this mobile service. Application version hosted at production slot does not contain authentication. Application version hosted at development slot has authentication and it works well. So, my client app can get authentication token and access protected API, and work with service hosted at development slot. When I swap this slots, client app still can get authentication token, but can't access protected API. I getting error 401 unauthorized on any attempt to call API using acquired token.
I'm using a custom authentication as described in docs
Both slots is identically configured: authentication: enabled, action to take when request is not authenticated: allow anonymous requests, authentication providers: disabled. As far as I can understand the one and only difference between those slots is URL. It looks like when the url of service is changed, it starts to generate invalid tokens.
That can be a cause of this behaviour?
For anyone else coming across this question, there are a few additional things to consider when using Azure authentication and slot swap. First, the Azure team has corrected the hostname issue, so all slots have the same hostname (you can verify this in the Environment settings for each slot). Tokens generated on one slot are now completely valid on all other slots.
HOWEVER, when a token is generated, it is stored in a folder on the hard drive of each slot, and that folder is not sticky to a specific slot. This means that if you have client users using a token for your production slot and you swap production and staging slots, that client's token WON'T be valid anymore (because their token reference that was on the production slot is now on the staging slot).
This may or may not be an issue for your app. If you require users to log in frequently, then they may not even notice the extra need to login. If however you have long lasting tokens (like most social networking sites) then this can cause some headaches.
One of the parameters that involved in token creation process is hostname. In my code hostname value was provided from MobileAppSettings. The problem was that MobileAppSettings return the hostname value of development slot after the slots swap, so the generated token is invalid. Service restart fixes this behaviour.
Related
I've created an App Registration in Azure. I've then created a secret, and copied the value. The value doesn't contain any characters that need to be URL Encoded.
I've then granted the App Registration permissions on the downstream API that i want to call, via the "Expose an API" functionality - adding it to "Authorized Client Applications", and granting it a "Read" role.
I've then set a Redirect URL that matches the localhost i'm running it from, and enabled Implicit & Hybrid flows.
Once done, i've configured the API that i'm calling the downstream API from, in the same way that i've configured another previously (In fact, i just swapped the values out in AppSettings.json for testing purposes - so i know it's setup correctly, as it works with other values)
I've done this before - but the difference was that we had an Enterprise App behind the App Registration, and this time we do not. (I just wanted an App Registration to Authorise with).
So - the error i receive is always:
AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app
Any ideas as to where i may have gone wrong here?
I should mention that i've tried to generate several different Client Secrets, with varying expiration times, and ensured that none contain odd characters that i've seen mentioned before (hence the url-encoding comment above).
In addition, i've compared the two app registrations (as mentioned, the one backed by Enterprise App), and found no relevant differeces - but one works, and the other not.
EDIT: These are the steps i've taken to setup the App Registration:
https://learn.microsoft.com/en-us/azure/databricks/dev-tools/api/latest/aad/service-prin-aad-token#--provision-a-service-principal-in-azure-portal
I've then granted that app rights to call another API.
Still, it insists the Client Secret is wrong.
I have Registered two apps in Azure AD; One being the Server and the other being the Client as one set. There are two sets created; One set for Production and the other being for UAT. Client Apps are types of "Web" and none being as SPA.
Production Server App is almost a clone of the UAT Server App. And Production Client App is almost a clone of a UAT CLient app.
Consumers use Client Apps to get tokens by using the OAuth 2.0 token endpoint (v2) https://login.microsoftonline.com/[--Tenant--]/oauth2/v2.0/token as Client Credential Flow with a Secret. The token generated is used as a bearer token to Authorize my Web API.
On the Production Client App, it returns an error when retrieving Token from Token endpoint and it read as:
AADSTS9002326: Cross-origin token redemption is permitted only for the 'Single-Page Application'
Whats Bizzare here is:
Production Client App can get Token from Public Network (Internet), but not in Internal Network (Having Internet access)
UAT Client App produces Tokens from Public and Internal Networks (Having Internet access).
With such facts, it's not rational to say that there is a network restriction in the Production Consumer site. I am clueless on why App is not producing tokens in Internal networks but in Public networks, whereas the UAT Apps have no issue in producing Tokens irrespective of the environment.
This case almost elaborates my case but I have checked mine, where Client App is Public and Server App is Private.
Where to search? What areas to looking to?
In case someone else encounters this error, check the URIs type in the Manifest file to be Spa and NOT Web. Even if you have set the platform in Authentication to Single-page applications, the URIs type might still be set to Web which will cause this error.
My understanding: In an Azure App Service, you can set the service to basically never "fall asleep" by setting the "Always On" setting in Azure Portal.
While this is an easy change to the service, I am trying to avoid having the service constantly run when not in use, and driving up the monthly expense of hosting the service.
My dilemma is that I have an Azure App Service running, which I authenticate a Xamarin Forms app against. In the process of logging in, I return an OAuth token to the client which is set to expire in 15 days (something long for testing).
Everything works fine while the Azure Service is running, but if the Azure Service "falls asleep" then I am forced to login again - which leads me to believe that the tokens issued by the service have been lost after the service falls asleep.
My question is: Is there a way to store the current tokens in an Azure Table Storage (or something) prior to "falling asleep", then pull from the same storage when the service "wakes up"??
I did find the below question, but couldn't get a clear understanding of how to persist the bearer tokens:
How are bearer tokens stored server-side in Web API 2?
I have been searching high and low with clear indication of how to do this, let alone if this is even possible.
Any help would greatly be appreciated.
The answer of How are bearer tokens stored server-side in Web API 2? you find is right. Usually, we will store the access token in client side. You can store it any place in your clients, local storage, sqlite, even files. Just to make sure, your application can get back the access token.
When your application send HTTP requests to the protected server, you will set the access token in Authorization header.
And your server once get a HTTP request, it will verify the token and authorize the user.
I am using Azure Mobile Apps with deployment slots, with the service provider for login being Microsoft. I have some odd behaviour, during swapping and the users relogin.
Is the performance better/different for AD? [read that it was not for GA yet?]
I am developing in a developer slot with everything specifically configured for this environment, the test and updates are working. I upload the server to staging, now utilizing the same db and settings (except microsoft authentication). The server is again verified to be working both on client and server.
I then use swap to change the staging and production slots. The production slot has the microsoft account login settings.
Upon swap the login by users are continuing indefinitely (no timeout, i.e. several minutes running without any stop) if, the referesh token call is made, as per this link:
//retrieve user info
user = new MobileServiceUser(credential.UserName);
credential.RetrievePassword();
//refresh token
user.MobileServiceAuthenticationToken = credential.Password;
JObject refreshJson = (JObject)await ((App)Application.Current).MobileService.InvokeApiAsync(
"/.auth/refresh",
System.Net.Http.HttpMethod.Get,
null);
My initial question is therefore is it possible to insert a timeout e.g. 2 seconds on the call to force the user to re-enter their credentials?
Because it seems to work if the user logs out and then back in with normal login procedure:
user = await ((App)Application.Current).MobileService.LoginAsync(provider);
credential = new PasswordCredential(provider.ToString(), user.UserId, user.MobileServiceAuthenticationToken);
vault.Add(credential);
string newToken = refreshJson["authenticationToken"].Value<string>();
Question(s)
Is it possible to insert timeout on MobileServiceClient.invokeApiAsync calls?
Is there some setting that can be set so the swap mechanism does not introduce this issue?
Is there a way to improve the login/relogin flow, the users are complaining that the login is failing often. I cannot replicate it in other instances than during the swap. Can this be because of distance to the server?
Therefore would Traffic Manager be a solution? However, I cannot see how it should be enabled if I am using microsoft login. Since a service is bound to an application name for authentication. How should the Traffic Manager be used in this respect?
Is there some setting that can be set so the swap mechanism does not introduce this issue?
Not sure if this applies to your case, but there is a known issue where certain app settings can actually cause issues with swapping. Do you have any app settings defined that end with _EXTENSION_VERSION or that start with WEBSITE_AUTH_? If so, try removing them and see if that resolves the issues you're seeing.
Is there a way to improve the login/relogin flow, the users are complaining that the login is failing often. I cannot replicate it in other instances than during the swap. Can this be because of distance to the server?
I've never head of an issue like this. Anymore details on the failure you can provide, such as a status code? One thing you can do is enable Application Logging and you should be able to get detailed information about the refresh failures.
Therefore would Traffic Manager be a solution? However, I cannot see how it should be enabled if I am using microsoft login. Since a service is bound to an application name for authentication. How should the Traffic Manager be used in this respect?
I think the way to make this work is to use a single Microsoft account application for all mobile app backends that are being load-balanced by traffic manager. The redirect URL that gets configured needs to use the common host name that is registered with Traffic Manager.
Is it possible to insert timeout on MobileServiceClient.invokeApiAsync calls?
From the API, It seems we can not set timeout in this method, refer to https://msdn.microsoft.com/en-us/library/azure/mt691682%28v=azure.10%29.aspx?f=255&MSPPError=-2147217396 for more details.
I have 2 webapi2 projects that use the same database. If I'm on localhost I get a bearer token from one I can pass it to the other and the other will properly decrypt it and load the user. However when I publish them to separate urls on azure, I get the one token fine from one but when I pass it to the other I can't get the ticket to load and it gives me the unauthorized response.
I'm testing this by watching the owin AuthenticationTokenProvider.OnRecieve method. When context.DeserializeTicket is called the ticket remains null and the user never gets loaded.
Your first response will likely be about how the machine keys need to be the same between the 2 so they will work. The problem there is
All my online research says that azure machine keys are synced between apps in the same role (ones a web app and the other is a web api app) so this shouldn't be an issue
I can't specify a machine key because the first app has been in production for a while and changing it's machine key would mess up stored passwords etc...
using the machine key used by the production app on the new api nay work but there is no way to get the machine key of an azure web app.
I'm pretty sure this isn't a machine key issue though but I have no idea how to figure this out. Heeeeelllp!