I use an Azure Mobile Serivce to save data from my app useres in my Windows 8 Store App. I want to publish the app in the app store but for this I have to be sure every user can only get his own data. If 10 people upload data to my Azure service they should only be able to get their own data. How can I do this?
You should check the Use scripts to authorize users in Mobile Services tutorial it will show you how to partition the data per user
Basically you have to write custom scripts server side (directly in the Azure Portal in the Mobile Service script section) for the Insert operation like this
function insert(item, user, request) {
item.userId = user.userId;
request.execute();
}
And the Read operation like this
function read(query, user, request) {
query.where({ userId: user.userId });
request.execute();
}
But first you will have to add authorization to your app as shown in the Get started with authentication in Mobile Services tutorial
Related
The task is to download google sheet in excel format and store it in Azure blob storage on timely basics using the Azure time trigger function.
Access Method to users google drive - OAuth Client ID.
I have created an Azure function locally and it works fine as expected and performs the task but when I deploy azure function I get this error.
Code for DriveService where the error occurs according to stack trace when deployed
public string[] Scopes = { DriveService.Scope.Drive, DriveService.Scope.DriveReadonly };
public DriveService GetService()
{
UserCredential _credential;
//Error Occurs at line below
Google.Apis.Auth.OAuth2.Flows.GoogleAuthorizationCodeFlow googleAuthFlow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer()
{
ClientSecrets = new ClientSecrets
{
ClientId = _config[Constant.ClientId],
ClientSecret = _config[Constant.ClientSecret],
}
});
string FilePath = Path.GetDirectoryName(_driveCredentialsPath);
_credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
googleAuthFlow.ClientSecrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(FilePath, true)).Result;
DriveService service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = _credential,
ApplicationName = Constant.ApplicationName,
});
return service;
}
I think there are two situations where it can go wrong but I am not sure about it.
When I am running the application locally a consent screen appears and gives permission to access the drive.
When this same function is running on azure who and how it will grant permission to access the drive.
I have provided my Azure App URL on Google OAuth Consent Screen as mentioned below to overcome this situation.
When I am running locally after giving permission to access drive it creates a TOKENRESPONSE-USER file a which consists of the access token, expiry date refresh token, and scope.
Is this possible that when the function is deployed it is unable to create a TOKENRESPONSE-USER file on azure function?
Please let me know why I am getting this error or do I need to change something in my process.
You can configure your function app to use Google login for authentication purposes when running on Azure. To achieve this you have to generate client id and client secret using the Google sign-in for server-side apps, using this connection you can store the tokens obtained in the token store. Please refer to this document to configure your function app to use Google Login, refer to this document regarding the token store and how to retrieve and refresh the token obtained.
I can successfully run the fabrics example to query/insert to ledger.
I want to build a nodejs web portal and I already directly wrapped query.js in my web app code.
Now the question is, how to authenticate a user the webportal? Since the example query.js has code like:
...
return fabric_client.getUserContext('user1', true);
}).then((user_from_store) => {
if (user_from_store && user_from_store.isEnrolled())
//successfully authenticated user1
I noticed the cert/private key/pub key files in
/hfc-key-store
user1-cert
user1-private.key
user1-public.key
Do I need to post any of the keys through parameters or do I create a separate regular username password control?
In my opinion you can create a normal login system for the web portal using a database to store the credentials of the users.
In this database you can associate the user to a specific key, which is retrieved each time the user successfully login in the web portal.
In this way, you will have two different levels of authentication:
one associated to the web portal (username and password)
and the other one associated to the blockchain (the certificate to
write and read).
I've seen that when using ADAL.js, you cannot get group membership claims due to some URL limitation.
https://github.com/AzureAD/azure-activedirectory-library-for-js/issues/239
I am using oauth-bearer authentication from the frontend, that is, the frontend triggers a login via the AD login page.
The client then pass the access token to the backend.
What I want to do:
I want to filter some data in my backend endpoints depending on group membership.
e.g. if you are a member of group "London" in AD, you should only see things related to London in our DB queries.
Super simple using e.g. Okta or Auth0, not so much with Azure AD.
I also want to accomplish the same thing on the frontend, that is, show and hide menu items depending on group membership.
(All access is still checked on backend also)
The documentation is sparse and not very helpful.
"You should use Graph API".
How?, how do I talk to graph api using the token I get from the frontend?
This is the setup I have for my Node+Express endpoints:
app.use(
"/contacts",
passport.authenticate("oauth-bearer", { session: true }),
contacts
);
How, where and when should I call the graph API here?
Our system is super small so I don't mind using session state.
Can I fetch this information when the user logs in?
How should that flow be? client logs in, once logged in, call the backend and request the groups?
When you get the access token from Azure AD after the user logged in, you can find the group membership of the user by doing a GET request to https://graph.microsoft.com/v1.0/me/memberOf with the access token like this:
function getGroupsOfUser(accessToken, callback) {
request
.get('https://graph.microsoft.com/v1.0/me/memberOf')
.set('Authorization', 'Bearer ' + accessToken)
.end((err, res) => {
callback(err, res);
});
}
This sample assumes you are using the NPM package superagent.
And the required permissions to call this API are listed here.
I have developed Azure API app with authentication on feature, log in with Azure Active Directory, I need to consume this API from SharePoint online , I
I need to authenticate and consume the azure API, no signin-prompt, every thing should be handled in the script
need to use ADAL.js to authenticate secure API ,I cannot find any good reference about the JavaScript code, I was wondering if anyone have a good reference how the JavaScript code should look like?
Thanks!
Here are the steps to call the azure hosted API from SharePoint online using JavaScript and ADAL.js library, no signing-prompt, everything should be handled in the script using ADAL.js to authenticate secure API
Create and Configure API
Create azure API
Publish your azure API in azure
Browse to azure portal, select your API application , select Authentication/Authorizations
Set the App Service Authentication: On
Action to take when request us not authenticated: Log in with Azure dictionary
Authentication providers: Express
Now the API is protected with Azure AD, if you navigate your API via browser you will be prompted for login
When we set authentication in Express mode, the app will be created automatically in Azure Active directory, you can see the name under Azure AD app
Navigate to Azure management portal, click on active directory in left navigation,
Click on the Directory which will be federated to your office 365 (or any source you want to call azure API which uses the same azure active directory as your configured for you API authentication)
Click on the Application, and you will find you AD app in the list which has been created with Express method as we discussed om step nr.3
Now we need to create new app in AAD which will be our communication channel from office 365 to Azure API, Click on ADD on footer
Enter name and select “WEB APPLICATION AND/OR WEB AP” option
For Sign in URL enter your SharePoint online Url which you are planning to call Azure API from
For APP ID URL, enter unique Url, this will be used as a unique logical identifier for your app.
After the app created, click on Configure, copy the Client ID which will be used later
Under Permission to other applications, Click “Add Application”, on the next page select “All Apps” and select you Azure API app which you double checked in step nr.8, and confirm
You will be redirected back to Configure page, Under Permission to other applications, now you see your azure API app is listed here, click on delegated permission, select the access to app
At the bottom of the page, click Manage manifest > Download manifest.
Download the file to a location where you can edit it.
In the downloaded manifest file, search for the oauth2AllowImplicitFlow property. Change the value of this property from false to true, and then save the file.
Click Manage manifest > Upload manifest, and upload the file that you updated in the preceding step.
Azure management portal, select setting and copy your AAD subscription ID for related AAD
Call Azure API from SharePoint Online
Once the above steps have been done, you can call azure API from sharePoint online which is using same Active directory above
Edit the page and add Script Editor web part
Add following script
· subscriptionId, see step nr.20
· clientId see step nr.13
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.13/js/adal.min.js"></script>
<script type="text/javascript">
function CallAzureAPI() {
"use strict";
var subscriptionId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
var clientId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
window.config = {
subscriptionId: subscriptionId,
clientId: clientId,
postLogoutRedirectUri: window.location.origin,
endpoints: {
AzureApiUri: 'https://xxxxxxxxxxxx.azurewebsites.net'
},
cacheLocation: 'localStorage'
};
var authContext = new AuthenticationContext(config);
var isCallback = authContext.isCallback(window.location.hash);
authContext.handleWindowCallback();
if (isCallback && !authContext.getLoginError()) {
window.location = authContext._getItem(authContext.CONSTANTS.STORAGE.LOGIN_REQUEST);
}
// If not logged in force login
var user = authContext.getCachedUser();
if (user) {
// Logged in already
console.log(user);
}
else {
authContext.login();
}
// Acquire token for Files resource.
authContext.acquireToken(config.endpoints. AzureApiUri, function (error, token) {
// Handle ADAL Errors.
if (error || !token) {
console.log('ADAL error occurred: ' + error);
return;
}
var ApiUri = "https://xxxxxxxxx.azurewebsites.net/api/Get";
$.ajax({
type: "GET",
url: ApiUri,
headers: {
'Authorization': 'Bearer ' + token,
}
}).done(function (response) {
console.log('Successfully called API.');
console.log(response);
}).fail(function () {
console.log('Calling API failed.');
});
});
}
</script>
<input type='button' value='Call Azure API' onclick=" CallAzureAPI ();"/>
This solution works though after some time ( later I found out when AAD cookie is expired ) we get this error "Token renewal operation failed due to timeout ",
I did some research and I found out he getCachedUser or getUser methods look into the browser storage for id_token and returns a non-null user if there is a token inside the cache. It does not look into the token expiration time though.
What's happening here is since localStorage is used, tokens are preserved in the cache when one re-opens the browser (and hence getCachedUser returns a non-null object) but the AAD cookie is expired (unless user checked the keep me signed in checkbox when logging in). Since the cookie is expired, acquire token call fails with the "login required" error.
so as workaround I checked , keep me signed in checkbox when logging in and it works .
It is possible to call the web API which protected by Azure AD from the SharePoint online using the JavaScript, however it is very complex.
Here are the steps for your reference:
Developing the web API which protected by Azure AD
register an native app on the same tenant
enable the implicit flow for the native app
grant the native app to access the web API from Azure portal
using the admin_consent for the native app to grant permission fo the organization
developing a web page in web API project for the redrect page for the OAuth 2.0 request
write the code in the web page using windows.postMessage to post the token to the parent page
$().ready(function () {
if (window.parent != null) {
// get the token from URL here
var token = "123";
console.log(window.location);
window.parent.postMessage(token, "*");
}
})
In SharePoint online page, using iframe to send the implict flow like code below
<iframe id="iframe_id" src="https://login.microsoftonline.com/{tenanit}.onmicrosoft.com/oauth2/authorize?response_type=token&client_id={clientId}&resource={webApiAppIdUri}&redirect_uri={redirect_uri}&prompt=none"></iframe>
<script>
var token = "";
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
token=event.data;
console.log(event.data);
}
</script>
Here is a figure to help understanding the progress:
I am using the following code in an Azure Mobile Service API. but I am not getting any response or error. If I go specifically for ideitities.google or facebook I get error 500 Internal Server Error. In log it appears as if the identities is null. whereas I am loggedin to gmail and facebook with the current browser session..
Error in script '/api/test123.js'. TypeError: Cannot read property 'google' of null
at Object.request.user.getIdentities.success
exports.get = function (request, response) {
request.user.getIdentities({
success: function (identities) {
//response.send(statusCodes.OK, identities);
// request.respond(200, identities);
response.send(statusCodes.OK, identities);
// Do something with identities, send response
},
error: function (err) {
// handle errors
}
});
}
What am I doing wrong? I have also enables the preview user feature using the Azure CLI but no effect.
The identities you get back from that call are identities used to authenticate with the mobile service. Just being logged into google in your browser session has nothing to do with the identities in your mobile service.
The mobile service is going to read the signed JWT token you are sending with the request and provide you the identities. That token is generated when you call the login method on the mobile service.
To login using an existing token from google or facebook, you can use this API:
http://msdn.microsoft.com/en-us/library/azure/jj710106.aspx
To have mobile services initiate the login process with the provider (i.e. show you the OAuth login for the provider) then you can use this API:
http://msdn.microsoft.com/en-us/library/azure/dn283952.aspx
Note that for this to work you have to have previously setup your mobile service, on the identity tab, with the information about your application setup with that identity provider. Also, all of the client SDKs for mobile services provide login methods that wrap these REST API calls.