I want to retrieve an access token for the Microsoft Graph API from within a script running on a Sharepoint page. This blog post describes what I want to do:
Now, imagine that you want to directly read the value of the Access Token, because you want to use it manually in a low-level REST request [...] using any other HTTP low level request like AJAX, jQuery, etc.
The post then says
Of course, in order to access the Access Tokens, you can directly access the Session Storage variables by key.
When I inspect the sessionStorage for a Sharepoint page, I see that the MS Graph API token is stored under a different domain associated with https://webshell.suite.office.com and the associated Iframe. It would seem that this token is therefore inaccessible from a script running under the whatever.sharepoint.com domain.
Does this mean that I need to create an SPFx app to access this token?
Related
I'm following this tutorial to get the track list from my Discover Weekly playlist. The tutorial mentions that I need to get an OAuth token for my own account before requesting the playlist info. This is done by going to a random Console page and click on 'Get token' at the end of the page (which requires me to log into my Spotify account and approves the Console to access my account data).
However, I want to acquire this token programmatically, instead of manually clicking on 'Get token' and logging into my account every time I need this token. What I have is:
My Spotify user ID (from my Account page)
The Spotify client ID for an application I just created under Spotify for Developers
The client secret for this application
Basic knowledge of how to send GET and POST requests (using Python's requests library)
How can I get an OAuth token, or at least generate a new token each time, using some of these above
information?
It depends on what you're trying to do. If all you want is a token to query the api to lookup songs/artists/etc., then you can use the Client Credentials auth flow that doesn't require any user input. All you need to do here is exchange your client ID and secret for an access_token that you'll use in subsequent requests.
If you want access or change certain user information, you'll have to use one of the two other flows on the same spotify authorization page. You'll need to pass a list of scopes with this request, directing the user to a spotify-url-based authorization page, and be able to give it a redirect url that will handle the receiving of the access_token object once the user logs in to the spotify page.
I don't think there's a way to implement one of these flows where you need to request user scopes without having some sort of web server running to accept the redirect passed into the spotify auth url and then save the given token.
After looking at the link you posted for spotify's console pages, it looks like you can use any of those API requests to generate a token including the scopes you want. All it's doing is performing the normal authorization flow in the background, skipping the step where it returns a secret to you that your server that you can then exchange for an access_token and refresh_token. Using the spotify console pages seems like an easy quick way to get scripts or prototypes running without having to deal with setting up your own webserver.
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
I'm creating a client-side application (i.e. HTML/CSS/JS in a web browser) that retrieves survey information from a SurveyMonkey account and generates an appropriate form to submit it. The application itself works fine, but it relies on knowing the API key to call get_survey_list and get_survey_details. The problem is that anyone could easily extract the key (e.g. by inspecting the network requests using the browser's debug tools) and perform more privileged operations like get_responses which is private information and thus should not be publicly accessible in this way.
Is there a way to create a "limited access API token" of some kind? For example, I would like to create one that is only authorized to perform certain types of API calls.
This is not possible, the only authorization token you can generate is a full access one as documented here.
Your best bet in this case is to have a proxy web app you can call, which then makes the API calls on the client's behalf.
I would like to know if there is a way within OAuth to limit the data a user can see once the token has been accessed. For example, in the 'photo sharing' sample where one application contains a list of photos and another application wants access to the photos for printing purposes. How can the user indicate the photo print service should see a subset of the photos? Maybe I only want the printing service to see photos with a .jpg extension, or photos with after a certain date, or with a certain 'tag'. Where can additional authorization requirements be populated?
I have a java application and we are using Spring Security OAuth2 and hopefully we can accomplish this.
Thanks
For instance, you can use 'scope' for that purpose. Define a custom 'scope', and the endpoint of your service should interpret the custom scope and behave based on that.
For example, define 'pic_jpeg' as a scope name and describe about the scope in your API document like "'pic_jpeg' scope is required to access JPEG pictures."
A client application will access your authorization endpoint with a parameter 'scope=pic_jpeg scopeX scopeY', and your OAuth 2.0 authorization server implementation will finally issue an access token which is associated with the scopes (pic_jpeg scopeX and scopeY). The client application then accesses the 'pictures' endpoint of your service with the access token, so the endpoint should confirm that the access token is associated with 'pic_jpeg' scope and allow the client application to access JPEG pictures only when confirmed.