I'm writing my first flask app and using the spotify api. I want to pass the access token from this api into java script like so
var token = "{{ token }}";
fetch('https://api.spotify.com/v1/me/player/currently-
playing', {
headers: {
'Authorization': `Bearer ${token}`
}
I'm doing this outside the flask app so I can frequently update the json data to the webpage easier. This method doesn't seem secure so I was wondering what is the perferred method in a situation like this.
Since your example is almost literally straight out of the Spotify Authorization Documentation and it is in relation to accessing the Web API, you're good.
If you were auth'ing on behalf of a user for more serious actions then you wouldn't be making client side requests.
Since the token you're using can be revoked and does in fact expire, you can store it in your db in plaintext.
You can store keys/secrets using Microsoft's Azure Software. Once you register you'll have access to those resources. You can set the secret in the secrets file in your azure portal and reference the secrets from there in your application source code.
Related
I am trying to list my GitHub public repos on my public website using their REST API. I have been creating personal tokens so far. In localhost it works.
When I do the request from my site it responds a 401 and it deletes my token.
To get the repos I am doing this simple request:
async function loadRepositories() {
const token = 'my_token';
const response = await fetch("https://api.github.com/users/tauromachian/repos",
{
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
}
);
const repositories = await response.json();
return repositories;
},
How can I get this done?
Github is trying to protect you from someone stealing your identity here. There are ways to detect if a HTTP request is sent from the browser or a server (it's not 100% reliable though).
As you make the request from the browser which is a public client, meaning everyone can read the code and hence secrets you use within the code you are exposing your Personal Access Token (PAT). This PAT identifies you against Github, therefore if someone else could get hold of it, they can impersonate you and e.g. delete repos, steal code etc. (if the token has the correct scopes).
As Github wants to prevent that from happening, they delete tokens which are publicly exposed (they know it's exposed as the the request comes from a browser). Therefore attacks like that are not possible anymore.
To make your website work however you can simply make the request from your server as you can securely store secrets on the server-side and call the endpoint of your server from your website. Once you do that, Github won't delete the token, your token is save and you can display the data on the website.
I am creating a login page. The idea is to take the username and password then use that to get an id token from AWS cognito user pool.
Then I need to store the token in a database and transfer that token to index.html along with the username. This is because index.html needs the token to make a post request to an API gateway using the same id token and it needs to know the user name to keep track of which user is currently logged in.
Now the index.html has to check if the token transferred to it matches the token in the database or not.
If it does and the token is not expired, then there is no redirection, otherwise, the index.html redirects to login.html.
The problem is my back-end completely relies on Amazon Lambda functions and API gateways because my company does not want me to use any back-end language. Now, I found that lambda functions could not set browser cookies nor read browser cookies.
This left me no choice but to use javascript cookies, sessions and local storage to transfer the token and username to index.html. However, this approach is considered to be insecure.
There aren't any tutorials on a secure login system using cognito.
Note: Any other secure login system will do the work, but remember I need to pass username and password to user pool to get an ID token which means, if I use any other login method, then I would now need to pass username and password both to index so that index can make a request to user pool to get an id token and make a request to the API gateway.
Now my question is, is there a way to actually transfer data to index from login without compromising security? Can I use lambdas in any other way to transfer the tokens?
Please help. Thanks in advance.
Now, I found that lambda functions could not set browser cookies nor read browser cookies.
I don't think this is strictly true.
Using Lambda Proxy Integration gives your Lambda function visibility into and control over many aspects of the HTTP request. This includes setting and reading arbitrary headers (including set-cookie).
To demonstrate, you can set a function like this up and attach an API Gateway trigger (with Lambda Proxy Integration enabled) to it:
exports.handler = (event, context, callback) => {
var returnobj = {
"statusCode": 200,
"headers": {
"Content-Type": "application/json", "access-control-allow-origin": "*",
"Set-Cookie": "testcook=testval; path=/; domain=xxxxxxxxxx.execute-api.us-east-1.amazonaws.com; secure; HttpOnly"
},
"body": JSON.stringify({})
};
console.log("headers", event.headers.Cookie);
callback(null, returnobj);
};
This function returns a Set-Cookie header that the browser will respect and send along with future requests to this domain. If you hit this in a browser twice, you'll see the cookie sent by the browser and logged by the lambda on the second request.
If you aren't willing to use Lambda Proxy Integration, you can probably still pull this off by mapping part of your Lambda response to a header in API Gateway.
I'm trying to get information about videos hosted by Vimeo (from my client's channel, so no rights issues). I'm using Javascript, specifically d3.js.
The request works fine when using the old API, with this type of url :
http://vimeo.com/api/v2/video/video_id.output
For instance, this works in d3.js :
d3.json("http://vimeo.com/api/v2/video/123456789.json", function(error,data){
console.log(data);
}):
But I can't get the new API to work as easily in a simple request, using this type of url for instance :
https://api.vimeo.com/videos?links=https://vimeo.com/123456789
What do I need to do ? Authenticate ? If so, how ? I'd be grateful to get examples in either jQuery of d3.
Vimeo's API documentation is not the best, so you have to dig a little around to actually get the information you need. In your case, you do not need to go through the whole OAuth2 loop if you are simply requesting data from endpoints that do not require user authentication, such as retrieving metadata of videos, as per your use case.
First, you will need to create a new app, by going to https://developer.vimeo.com/apps:
You can simply generate a Personal access token from your Vimeo app page under the section that says Generate an Access Token:
Remember that this token will only be visible once (so copy it when it is generated): and you have to keep it secure! The access token should be part of the Authorization header's bearer token. If you are using cURL, it will look like this:
curl -H "Authorization: Bearer <YourPersonalAccessToken>" https://api.vimeo.com/videos/123456789
Therefore, while you can do the following on your page to retrieve video metadata on the clientside, note that you are actually exposing your private token to the world:
d3.json("https://api.vimeo.com/videos/123456789/")
.header("Authorization", "Bearer <YourPersonalAccessToken>")
.get(function(error, data) {
console.log(data);
});
However, I strongly recommend that you proxy this request through your own server, i.e. create a custom endpoint on your server, say /getVimeoVideoMetadata. This API endpoint will receive the video ID, and will add the secretly stored access token you have on your server before making the request. This will mask your access token from your website visitors.
I want to build something with dribbbble's API.
As I'm reading the API docs I need a HEADER set to my API_KEY.
var token = 'MY TOKEN HERE';
$http({
method: 'GET',
url: 'https://api.dribbble.com/v1/my_user',
headers: {
'Authorization': 'Bearer ' + token
}
}).success(function() { ... });
Its possible to hide the token, preventing users to see my API KEY in page source?
Can someone explain me whats the best practice using API KEYS in $http?
Your best bet is likely going to be to create your own web service and call the dribble api server side. There is simply nothing you can do to secure information like that client side.
It's possible that dribble validates your api requests as a combination of hostname & key so it may not be is significant of an issue as you perceive it to be.
tl;dr - Nothing is secure client side.
There is nothing you can do to completely protect your API key if it's somewhere in your JavaScript. Which is why a lot of third-party services ask you to provide the domain from which you will call their API so that they can validate the key only if it originates from the domain you registered.
The right way to protect your API key is to create a server-side wrapper that will make the request, and call that from JavaScript. And even having the API keys hardcoded in your server-side code is a bad idea - the best practice is to set them as environment variables.
I usually use this method when I need to create custom headers in Angular JS.
At the beginning of a Module using $http I set my headers for get and post like this.
$http.defaults.headers.get = { 'apikeyName' : 'yourkey' }
$http.defaults.headers.post = { 'apikeyName' : 'yourkey' }
These headers will then be send everytime you use $http in that module and you won't need to specify them each time.
Its possible to hide the token, preventing users to see my API KEY in page source? No, your Angular JS is client side so every client can see the key. (see answer above)
Kind regards
I'm attempting to get and store an access token from the Pocket API using Node.js. I am able to get the request token, redirect to the Pocket login page, redirect back to my site, and finally able to exchange the request token for an access token.
But that's where my problem lays. I don't know how I should go about actually storing the token, and without it I am unable to make API calls (of course). Here's the relevant code:
//called when Pocket API redirects back to /getAccessToken
function getAccessToken(response, requestToken) {
restler.post("https://getpocket.com/v3/oauth/authorize", {
headers: { "Content-Type" : "application/json",
"X-Accept" : "application/json" },
data : JSON.stringify({consumer_key:CONSUMER_KEY,code:requestToken})
}).on("complete", function(data, res) {
if(res.statusCode == 200) {
var accessToken = data.access_token;
console.log("Access granted: " + accessToken);
//BUT HOW DO I STORE THE ACCESS TOKEN FOR USE OF API CALLS ??
}
response.writeHead(307, {Location: DNS}); //go back to site
response.end();
});
};
I was thinking I should store the accessToken on the client side, but I don't actually know how to go about doing that. I've tried using cookies, but that didn't seem to work. Of course, I may have just implemented them wrong.
Your help is much appreciated.
How you store the access token usually depends on where you will be using the API.
I usually like to persist tokens in the database (like MongoDB) on the User document they are associated with, and then my web client can ping my server (via a RESTful endpoint) if it needs the token for anything. This way if the user clears all that state on the browser you don't have to go through the entire OAuth flow again.
you should probably make the cookies thing work. option 2 is to use localStorage but if you're struggling with cookies i wouldn't try going down that path - it gives you more control of when the tokens are sent across the wire but also requires a lot more work to make your serverside and clientside code coordinate.