I'm new to using Azure Active Directory authentication with a Web API. Right now the login page on my Single Page Application simple directs the user to the Microsoft login page where they enter their credentials and then are redirected back to my SPA. Upon the redirect the access token is now part of the URL. Is it possible to get that token via JSON rather than part of the URL? Is that a security risk making the token visible to user like that? If there is no other way to get the token what's the best way of processing that? Should I read the URL and pull the token from there and then redirect the user again to the actual website?
You have to be mindful in implicit flow the token will still be maintained at the client site (local storage normally). So even if you are hiding the token from URL , you still will be storing at client side and that's one of things you have to manage in SPA. You will have to send token with every HTTP request to your web api to get that authenticated on that end.
In implicit flow tokens are shortlives and you can't issue refresh token for longer period of access. For this kind of flow you need to use official library (ADAL.js)
https://github.com/AzureAD/azure-activedirectory-library-for-js
More resources
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-implicit-grant-flow
You can use ADAL.js library to acquire the token. There is a pre defined function which you have to call after the Ad authentication or at the beginning check if you are logged in, you can use isauthenticated function to check if you have already logged in, and use getaccesstoken function to acquire the token after authentication.
Related
I have a SPA that calls a PHP backend (based on Symfony currently for proof of concept).
Authentication for this application is based upon an Azure Active Directory, and all azure users are matched against the local application user table on their email address and OID - if not registered locally then a local account is created for them with basic privileges.
For authentication, a call to the backend which then redirects to Azure to authenticate, and then the access token is returned. Instead of re-inventing my own auth token system in the backend, can I just get the SPA to pass the Azure access token in the API calls and validate it on the backend, letting the SPA deal with refreshing the token as and when required?
Cheers
Yes - in this partial SPA model you will typically need to store a refresh token in an http only secure cookie. When the web UI calls an API and gets a 401 expired response it will need to call the back end to refresh the token.
I want to create a Lambda function that uses the Google Tasks API to add tasks every evening at a certain time.
I am unsure of how to authenticate with my account and be able to store access tokens / credentials securely in my lambda environment variables.
As I understand it since my lambda is making a request on behalf of a user (which will always be me in this case) it seems like everything in the docs points to needing to use OAuth2.0 to authenticate which makes sense since you'd want the user's permission to make changes in their account. However since I only want to do so on my account, I wanted to know if there was a way to simply authorize my account without doing a OAuth flow which I don't believe is possible from a lambda since I won't be responding to it every time it runs.
How would I authenticate my application so I can make calls to the tasks API and be authenticated against my account?
This is surprisingly more work than I'd imagined and unfortunately google doesn't generate developer tokens which would have solved a lot of this problem.
Authorization & Consent
There are no immediate ways of authorizing your account for the app that you've created without going through the consent flow. Some cloud service providers generate a developer token for testing your app with your credentials - but google doesn't seem to have this functionality. Not for the Tasks API anyways. AdWords API talks about a developer token but I'm not sure if it's the same concept.
You won't have to re-authorize once you've given consent. This general principal applies to other OAuth using parties, unless the level of consent changes (example: the app starts asking for write permissions in addition to previously consented read) you won't get re-prompted. If permission levels change, you'll get re-prompted.
Now - the second part - how do you make one?
Google explains it in detail here - but I'll further simplify because you don't need to setup a web-server for your case, you're only doing this for yourself.
Our goal is to only to get you the initial refresh token. Once you've retrieved the refresh token, you can use that from your Lambda to retrieve a new access + refresh token whenever you're accessing the tasks API. You just need to keep the refresh token stored somewhere, so you can continuously keep on accessing the tasks API. You're just looking to get the access + refresh token.
Head over to https://console.developers.google.com and create a new application.
After the creation, click 'Enable APIs and Services' and look for Tasks API.
Proceed with creating the credentials and make sure you select you'll be calling this API from a Web Server. Selecting Browser (JavaScript) would only give you an access token and not a refresh token, because they would trust you to store the refresh token on your server, but not on a browser. An access token is time-limited to (conventionally) 60 minutes.
You should also select the User Data / Information and not the App Data / Information for the types of data you want to access. The app one is generally used for GSuite.
Set your redirect uri to be http://localhost:8080 - This is where you normally would need a web-server but we'll just redirect back to your machine and get the parameter from here. It obviously won't find a web-server but the parameter we want is in the url, we'll just copy it.
Now here comes the authentication part. Google's auth url is: https://accounts.google.com/o/oauth2/v2/auth
We will add parameters to this url
access_type=offline // so your daemon app can access it offline
response_type=code // required if you have access_type=offline
scope=https://www.googleapis.com/auth/tasks // what do you want to access to
redirect_uri=http://localhost:8080 // where would google send the code
client_id=
so the whole thing should look like https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&scope=https://www.googleapis.com/auth/tasks&redirect_uri=http://localhost:8080&client_id=
Go to this URL and you should get prompted for consent.
Consent to it and google should redirect you to http://localhost:8080/?code= We'll need that code. That needs to be sent to google to get an access + refresh token.
Code exchange: Make a post request to Google. You can use PostMan. Again normally all of this would be automatically handled by a webserver (detect code parameter, make post request etc..) - but we just need the refresh token here, so we can stick that into our Lambda app.
POST to:
https://www.googleapis.com/oauth2/v4/token
with parameters:
code=<the code you've retrieved>
client_id=<your_client_id>&
client_secret=<your_client_secret>&
redirect_uri=http://localhost:8080&
grant_type=authorization_code
Google should return you the access token and the refresh token. From this point on you need to save the refresh token into your Lambda app - and if it's running on a scheduled job on every bootup:
Read the refresh token
Call Google for a new refresh token + access token
Save the new refresh token.
Use the access token to access your Tasks API.
I would like to upload a given file to Sharepoint. I'm using the Microsoft Graph API.
The documentation follows this workflow:
1. If no token, redirect the user to the Microsoft signin page.
2. The user is then redirected to the application, with an access token
3. Use access token to have an authorization bearer
4. Do what you gotta do...
My problem is the sign-in part. I don't want my users to be redirected to the Microsoft signin page. I want my application to connect and get the access token in the background (with cURL or whatever).
How can I do that? Why is the "open in browser" necessary?
I tried to replicate the sign-in process, but all I get back is the HTML response from the signin page.
Thanks in advance.
Your application act as a single-tenant service or daemon app.
The documentation about this scenario is here : https://developer.microsoft.com/en-us/graph/docs/authorization/app_only
The application must be registered in the AzureAD directory corresponding to the Office365 tenant
A first request is made by passing the application unique identifier and secret key as registered in the directory. This request returns an access token
The access token can now be used in the Authorization header of the following request to the Microsoft Graph API.
This method (of using Client ID and Secret) works well but there are other ways which may be better suited for similar scenarios.
The one major thing which is missing in access token generated this way is a user, meaning the token only contains the identity of the OAuth application (client) which called it but is not associated with any user for the request.
This could have a couple of implications:
Since the token is not associated with a specific user you will not know who performed the operation. In your example, you would not know who uploaded the file (and other similar information may be missing).
Access token without users will not work at all for some methods. For those, you need a delegated token.
Creating a delegated token requires some effort, if you are interested you can find the details in my article:
Getting Access Token for Microsoft Graph Using OAuth REST API
Can I use OAuth 2.0 without a browser (or an embedded browser in my app) to perform nightly uploads?
Setup I have a refresh token and access token from provider console-- Google Drive API
I wish to use Java SDK to use/reuse these to upload data without the requirement for any browser authorization once i have initially received my refresh/access tokens.
OAuth 2.0 requires a browser for user consent once
A browser is required, so that the user can agree to the request of the app to access the users data.
After the user agreed on sharing the data with the app, the app can use the refresh token without a browser based flow.
Documented here: https://developers.google.com/accounts/docs/OAuth2WebServer
Alternative for non-browser apps
You may use the OAuth 2.0 for Devices flow:
You app can act as a device which queries a code from google, displays it to the user, and asks the user to browse to a verification URL (e.g. with (system.out.println...).
So a browser is still needed, but your application itself doesn't need to provide a webpage to the user.
Yes. That is precisely what unattended access with the refresh token is about. When the user granted permission to the app, he was specifically prompted "... even when you're not logged in" (or similar, I can't remember the exact wording). You will store the refresh token on the server somewhere, and then use it to request an access token whenever your app needs to do its thang.
Just to clarify some of the wording in your question, the refreash and access tokens do NOT form a pair, so saying "reuse these", should actually be "reuse this", where 'this' is the refresh token.
When I call an oauth provider like gmail and I get the token back, how can I make sure that all future calls I make are from that same client that did the authentication? that is, is there some kind of security token I should pass pack? Do I pass that token back everytime?
For example, if I have a simple data table used for a guest book with first,last,birthdate,id. How can I make sure that the user who "owns" that record is the only one who can update it. Also, how can I make sure that the only person who can see their own birthday is the person who auth'd in.
sorry for the confusing question, I'm having trouble understanding how azure mobile services (form an html client) is going to be secure in any way.
I recently tried to figure this out as well, and here's how I understand it (with maybe a little too much detail), using the canonical ToDoList application with server authentication enabled for Google:
When you outsource authentication to Google in this case, you're doing a standard OAuth 2.0 authorization code grant flow. You register your app with Google, get a client ID and secret, which you then register with AMS for your app. Fast forwarding to when you click "log in" on your HTML ToDoList app: AMS requests an authorization code on your app's behalf by providing info about it (client ID and secret), which ultimately results in a account chooser/login screen for Google. After you select the account and log in successfully, Google redirects to your AMS app's URL with the authorization code appended as a query string parameter. AMS then redeems this authorization code for an access token from Google on your application's behalf, creates a new user object (shown below), and returns this to your app:
"userId":"Google:11223344556677889900"
"authenticationToken":"eyJhbGciOiJb ... GjNzw"
These properties are returned after the Login function is called, wrapped in a User object. The authenticationToken can be used to make authenticated calls to AMS by appending it in the X-ZUMO-AUTH header of the request, at least until it expires.
In terms of security, all of the above happens under HTTPS, the token applies only to the currently signed-in user, and the token expires at a predetermined time (I don't know how long).
Addressing your theoretical example, if your table's permissions has been configured to only allow authenticated users, you can further lock things down by writing logic to store and check the userId property when displaying a birthday. See the reference docs for the User object for more info.