I'm using Spotipy to get some spotify data from an authorized user but I can't understand how to authorize my account.
Am I correct in thinking that a server is required that hosts something at http://www.myapp.com/callback ? What needs to be returned? Maybe I'm completely missing something here... I'm very confused by the whole required redirect URI thing...
I am trying to make a program, without website, so how should I handle authorization? What exactly should the redirect URI do?
Thanks
Edit:
Using http://localhost:8888/callback as my redirect URI now and that works. I'm not even sure why since nothing is running on that port.
Disclaimer: I know nothing about Spotify's API. But I have worked with similar APIs in the past (or even designed them). What I assume is that they use some kind of OpenID/OAuth authorization mechanism.
The very nature of these APIs is that they work through the browser! The idea is that MyApp doesn't have your actual Spotify credentials, but instead some signed token it can use.
To communicate this token to the MyApp, there are the server-callbacks, outlined in your question. Because all the browser can do is to redirect to a special URL you provide, with some info added.
So there are conceptually two ways to deal with this:
the easy, server-based one: you in fact register a myapp.com. When your app tries to authorize with spotify, it first creates a unique resource (myapp.com/authrequests/HASH-NUMBER), and communicates this as callback. Then it goes through the motions of making spotify authorize it, and once these are finished, there will have been a call to myapp.com/authrequests/HASH-NUMBER/ADDITIONAL-INFO. So while your app is waiting for this to happen, it has to poll (or open a websocket and listen to that) myapp.com. Complicated? Wait, it gets better!
the harder, OS-dependent one: you write an application that registers itself as protocol-provider with your browsers. E.g. my company does that with the protocol "ableton". Thus we can make the browser generate "ableton://AUTHORIZATION-REQUEST-RESULT" URLs which will then be communicated through Browser and OS to the running application, and thus you receive the necessary secret.
HTH
Related
I created a Flask-Webservice with Python that runs independently inside a docker container. I then uploaded the docker image to an Azure Container Registry. From there I can create a WebService (for Containers) with some few clicks in the Azure Portal, that runs this container. So far so good. It behaves just as I want it to.
But of course I don't want anyone to access the service. So I need some kind if authentication. Luckily (or so I thought) there is a built-in authentication-mechanism (I think it is based on OAuth ... I am not that well versed in security issues). Its documentation is a bit sparse on what actually happens and also concentrates on solutions in C#.
I first created a project with Google as described here and then configured the WebApp-Authentication with the Client-Id and Secret. I of course gave Google a java script source and callback-url, too.
When I now log off my Google account and try a GET-Request to my Webservice in the Browser (the GET should just return a "hello world"-String), I am greeted with a Login Screen ... just as I expected.
When I now login to Google again, I am redirected to the callback-url in the browser with some kind of information in the parameters.
a token perhaps? It looks something like this:
https://myapp.azurewebsites.net/.auth/login/google/callback?state=redirxxx&code=xxx&authuser=xxx&session_state=xxx&prompt=xxx).
Here something goes wrong, because an error appears.
An error occurred.
Sorry, the page you are looking for is currently unavailable.
Please try again later.
If you are the system administrator of this resource then you should check the error log for details.
Faithfully yours, nginx.
As far as I now, nginx is a server software that hosts my code. I can imagine that it also should handle the authentication process. It obviously lets all requests through to my code when authentication is turned off, but blocks un-authenticated accesses otherwise and redirects to the google login. Google then checks if your account is authorized for the application and redirects you to the callback with the access token along with it. This then returns a cookie which should grant my browser access to the app. (I am just reproducing the documentation here).
So my question is: What goes wrong. Does my Browser not accept the cookie. Did I something wrong when configuring Google+ or the Authentication in the WebApp. Do I have to use a certain development stack to use the authentication. Is it not supported for any of the technologies I use (Python, Flask...).
EDIT
#miknik:
In Microsofts documentation of the authentication/authorization it says
The authentication and authorization module runs in the same sandbox
as your application code. When it's enabled, every incoming HTTP
request passes through it before being handled by your application
code.
...
The module runs separately from your application code and is
configured using app settings. No SDKs, specific languages, or changes
to your application code are required.
So while you are probably right that the information in the callback-redirect is the authorization grant/code and that after that this code should now be used to get an access token from Google, I don't quite understand how this would work in my situation.
As far as I can see it Microsofts WebApp for Container-Resource on Azure should take care of getting the token automatically and return it as part of the response to the callback-request. The documentation states 4 steps:
Sign user in: Redirects client to /.auth/login/.
Post-authentication: Provider redirects client to /.auth/login//callback.
Establish authenticated session: App Service adds authenticated cookie to response.
Serve authenticated content: Client includes authentication cookie in subsequent requests (automatically handled by browser).
It seems to me that step 2 fails and that that would be exactly what you wrote: that the authorization grant is to be used by the server to get the access token but isn't.
But I also don't have any control over that. Perhaps someone could clear things up by correcting me on some other things:
First I can't quite figure out which parts of my problem represent which role in the OAuth-scheme.
I think I am the Owner, and by adding users to the list in the Google+-Project I authorize them to use my service.
Google is obviously the authorization server
my WebService (or better yet my WebApp for Containers) is the resource server
and finally an application or postman that does the requests is the Client
In the descriptions of OAuth I read the problematic step boils down to: the resource server gets the access token from the authorization server and passes it along to the client. And Azures WebApps Resource is prompted (and enabled) to do so by being called with the callback-url. Am I right somewhere in this?
Alas, I agree that I don't quite understand the whole protocol. But I find most descriptions on the net less than helpful because they are not specific to Azure. If anyone knows a good explanation, general or Azure-specific, please make a comment.
I found a way to make it work and I try to explain what went wrong as good as I can. Please correct me if I go wrong or use the wrong words.
As I suspected the problem wasn't so much that I didn't understand OAuth (or at least how Azure manages it) but the inner workings of the Azure WebApp Service (plus some bad programming on my part). Azure runs an own Server and is not using the built-in server of flask. The actual problem was that my flask-program didn't implement a WSGI-Interface. As I could gather this is another standard for python scripts to interact with any server. So while rudimentary calls from the server (I think Azure uses nginx) were possible, more elaborate calls, like the redirect to the callback url went to dev/null.
I build a new app following this tutorial and then secured it by following the authentication/authorization-tutorial and everything worked fine. The code in the tutorial implements WSGI and is probably more conform to what Azure expects. My docker solution was too simple.
My conclusion: read up on this WSGI-standard that flask always warned me about and I didn't listen and implement it in any code that goes beyond fiddeling around in development.
I'm going to build an API in Flask for a (to be created) app which will be built using PhoneGap. In the API many calls will need authentication.
To get into the topic I was reading this tutorial on creating authentication for a Flask-built API. In this tutorial they first show how a user can use basic password authentication for every call, after which token based authentication is introduced.
As far as I understand, the client who calls the API should simply get a token and authenticate every subsequent call with that. In the meantime, the client should keep track of time and either get a new token every 9 minutes (before the old token expires) or simply keep on calling with the token until the client gets an Unauhorized Access message. Am I understanding this correctly?
Moving on, I wonder how it works with Apps on which you login on your phone and then are always logged in whenever you open the app (like for example the Facebook app). This is obviously more convenient to the user than always needing to provide the username/password and I would like to implement something like that as well. I wonder though; how is a permanent logged in feature like this implemented on the server side? Is it done by providing the password and username for every call, or using a never expiring token, or yet a different way?
All tips are welcome!
I've done what you want to do with:
Flask-security https://pythonhosted.org/Flask-Security/:
To manage users and permissions.
Flask-oauth-lib https://flask-oauthlib.readthedocs.org/en/latest/:
Provide oauth functionnality.
So, you have to take a look at Oauth flow, implements a user backend (like Flask-security) and implements an oauth server (with flask oauth lib for example) and bind it to your user backend.
After that, it's oauth standard flow. You just have to give the right token on each api calls and TADA !
With this way you can also, if you want, give access to your api to third-party app thanks to oAuth :)
I order to get access to the Facebook API on behalf of a user, one must get an OAuth access_token, the process is well documented (albeit it appears to be some undocumented requirements from FB) but from time to time I get this "Error validating verification code." when trying to exchange a validation code for an access_token.
There seems to be a lot of people having such trouble and most of the time the redirect_uri seems to be the issue, but here the redirect_uri is fine (it's exactly the same as the one passed to the auth dialog, ends with a slash and do not have funky characters or a trailing query string, I read almost all threads on SO about this issue and none of the proposed solutions did solve my problem)
What is the most intriguing is that when I check my logs, where I write the exact request url I use, and manually try it to get the access token, then it works. It is like the request is failing when the user logs in but works after some time.
So the fact that it is working after all seems to indicate that the request is fine but there is a problem on the Facebook side, like if there was some replication involved that did not complete between the time the auth dialog do it's thing and I try to exchange the code for a token.
I put in place a retry mechanism, hoping that the delay between two calls would be enough and the second call would succeed, but it doesn't work either.
Also, it's working most of the time and I cannot tell any difference between when it works and when it fails, only the user changes.
Any suggestion would be greatly appreciated.
I just bumped into this issue and solved it.
The issue was that I specified the redirect_uri in the oauth call to be http://apps.facebook.com/myapp/ instead of https://apps.facebook.com/myapp/ .
One thing that was kind of odd is that the exact same parameters worked if I entered them into the browser address field, but not as a server side request from the application.
It is possible on a per user basis to specify if you want to browse Facebook with or without HTTPS, so I recommend that you test with the setting at both modes when you test your authentication flow.
I'm writing panel for administrating nginx (domains, rewrites, etc), svn and other services. For that, i'm writing backend that will work on root (to change nginx configs, reload them, change user passwords, etc), and client (console client, and web app).
App works on unix sockets, and i made very simple protocol for it:
\0\0\0\0user\0key\0module\0command\0data\0
Well, this is quite simple. Client sends command and data to backend, fox ex:
\0\0\0\0morsik\0\0nginx\0add_domain\0www.domain.tld something\0
Problem is, how to authenticate that user is really morsik? For web interface i don't have to - web page have it's own authorization so i can sent some key that will work for every user that nobody will know.
Problem is if somebody have access to ssh. Then he could write simple client that will spoof username and then he could change other user configuration.
So, how can i made correct authorization for users?
Don't reinvent the wheel. ;) I found this discussion enlightening:
http://cyberelk.net/tim/2007/03/08/cups-unix-domain-sockets-authentication/ Explains the concept of socket auth.
http://pythonic.pocoo.org/2007/7/7/unix-socket-credentials-with-python Helpful details.
http://atlee.ca/software/pam/ This might work also, though less convenient.
Create a group for app admins only, etc.
I need to use Oauth for a personal twitter script I am making. Its not commercial or anything like that. To register it here: https://dev.twitter.com/apps/new I need a website even though it is a client. It wont let me register my app without a website.
Is there anything I can do? If I just created a blog that explains the concept behind the script I am using - would they accept that and let me register the "app" (just a script I use?).
If it is just for personal use, you could put pretty much any url in that field. As far as I know it isn't double checked or subjected to approval.
Choose Client here:
In place of Application Website you can put any link. Its just the link-back url.
As mentioned above, the callback URL can be anything, but I would choose Browser, not Client, because Twitter lets you override the value of Application Website with the parameter oauth_callback. This lets you automate the final step of the OAuth flow.
Usually, since you are running a script, you would need to set oauth_callback=oob and put the user through PIN authentication, which sucks. Here is an alternative:
Choose Browser and set Application Website to http://www.whatever.com (doesn't matter).
Register your script with your operative system to handle a custom scheme, eg: myscript://
Pass oauth_callback=myscript://anystring during the OAuth flow.
The result is that once the user is authenticated, Twitter calls myscript://anything from the web browser with the two last parameters you need for the final authentication step, and the OAuth flow will complete without user interaction.