from http://oyanglul.us
It would be awesome if we can use OAuth in JavaScript purely in client side.
before start to do that, please let me explain “OAuth2” with this picture in feeeew word (skip to section 2 YQL if you know OAuth2):
OAuth 2
OAuth 2 is widely use as authorize third party application without expose user’s password, OAuth2 using 2 steps verification. Take github as example:
There are 2 role in this story: Developer Oyang
and User Lulu
As Developer Oyang who write an App GIRA http://gira,oyanglul.us which can let user login using Github account.
As User, Lulu don’t want to login in your site with my Github username and password, since Lulu don’t trust Oyang but trust Github.
Solution should be: Oyang redirect Lulu to Github website so Lulu can login there, then github redirect to Oyang’s gira.com and with a signal: “hey, lulu’s password is correct, log she in dude!”.
So that is OAuth 2 actually.
Redirect users to request GitHub access
GET https://github.com/login/oauth/authorize
with parameter
-
cliend_id
: id of your application -
scope
: permissions your application should have
this will redirect Lulu to github oauth page. Lulu can now login in github then check the permission Oyang’s app request, and decide to accept or not.
GitHub redirects back to your site
if Lulu say “yes”, github will redirect back to Oyang’s app with parameter of a “valided code”. which means apps’s permited and now app can get the Lulu’s access_token
now.
POST https://github.com/login/oauth/access_token
with parameter
-
cliend_id
: id of your application -
client_secret
: password of your application -
code
: the thing you just got from github.
access_token
is just as important as User’s PASSWORD so keep that saft place and never expose to anyone.
client_secret
is your app’s password so never expose to anyone either
Done
now Oyang’s App Gira just got the access_token
of Lulu, so Gira can make requests to the API on a behalf of a Lulu.
Pure Client Side Implement
Now here comes the problems of Javascript OAuth 2 implementation pure client side.
- capture
code
in step 2 - secure
client_secret
when try requestaccess_token
when github redirect back with code
the first one is easy to solve by check window.location
$(window).on('eshashchange', function() { if(location.hash='#authdone'){ $.get("https://github.com/login/oauth/access_token",{ client_id:'666dc0b3b994cc362ca2', client_secret:'your secret', code:location.search.split('=').pop(); }); } });
as you can see the client_secret
has been expose to anyone who check you javascript code.
This is really serious problem since evil hacker can just use your client_id
and client_secret
to make an fake app of gira to steal your user’s information, horrible isn’t it.
now what, anyone can easily see your javascript from browser, where to hide your secret. no option but a server.
YQL
What is YQL
YQL is Yahoo Query Language. You can simpily use SELECT * FROM web
to get you data from any website. for example you can try put the follow query in YQL Console:
select * from html where url
“http://www.weibo.com/milhouse”=
amazing isn’t it, YQL will return the whole content of the website in XML or JSON.
check the bottom of YQL Console, simpily use request to THE REST QUERY will return the same thing. You don’t have to include any other third party annoying library to get your data. This is why I choose YQL other then Parse or Firebase as server side script.
Use YQL storage to keep secret safe
YQL provide online storage y.storage which allow you to store your YQL table, javascript and enviorment there. Since every thing is on sever, nobody but you can see them now.
When open YQL editor, you may curious about the 3 Key on the right side:
for each table/javascript/enviorment file you’ve create, there are 3 line for you.
- EXECUTE: use this link when you want to execute the content.this is really important for secure your secret, I’ll explain it latter.
- SELECT: when you just want to get the content.
- UPDATE: when update the content.
for better understanding, let me continue the Github OAuth example.
Here’s the plan:
- put all you secret inside enviorment file.
- create a table, data of the table come from javascript file,
- when the javascript is execute, request for the
access_token
- on the clientside, just request the YQL table for
access_token
. bang!
Create YQL Table
OK.lets do IT. First of all, we need create a table who can execute Javascript inside.
<?xml version="1.0" encoding="UTF-8"?> <table xmlns="http://query.yahooapis.com/v1/schema/table.xsd"> <meta> <sampleQuery>select * from {table} where code='meow';</sampleQuery> </meta> <bindings> <select itemPath="" produces="XML"> <urls> <url>http://oyanglul.us/gira</url> </urls> <inputs> <key id='CODE' type='xs:string' paramType='variable' required="true" />(ref:code) <key id="CID" type="xs:string" paramType="variable" required="true" />(ref:client-id) <key id="CSC" type="xs:string" paramType="variable" required="true" />(ref:client-secret) </inputs> <execute><![CDATA[ y.include('store://KqAGbe0nt2yi3bAnQQXxOx'); (ref:js-select) ]]></execute> </select> </bindings> </table>
FYI, the line (js-select) reference to the SELECT KEY
of the javascript file as follow, why SELECT
, you know when you use EXECUTE KEY
to referent an file, Yahoo will try to run it for you, but I don’t want the result of javascript but the code itself to define my table.
line (code) define the table should receive a key named “CODE”, and line (client-id) and line (client-secret) as well.
Create Javascript file
tokenRequest = y.rest('https://github.com').path('login').path('oauth').path('access_token');(ref:y-rest) var resp = tokenRequest.header('Accept','application/xml').query( { client_id:CID, client_secret:CSC, code:CODE }).post().response; response.object = {resp}
I know line (y-rest) is weird if you never use YQL before, so do I. This looks so lame to append path to address rather then jQuery way just $.get("https://github.com/login/oauth/access_token")
.
ok the CID
is parameter from YQL Table defined here, so does CSC
and CODE
.
finally, the Table and Javascript is done, how to use them, and where the hell should I put my secret to.
Create Enviroment File
Here comes the mighty enviorment file:
USE "store://jqozna9Rv9K0gS77jz8RI1" AS github;(ref:github-table) SET CID="666dc0b3b994cc362ca2" ON github; (ref:set-cid) SET CSC="your client secret goes here" ON github;(ref:set-csc)
the store://jqozna9Rv9K0gS77jz8RI1 is the SELECT KEY of your table just created. line (set-cid) and line set-csc pass the client_id
and client_secret
to github
table where the javascript can actually use.
Why My Secret is secure
if you use the SELECT KEY of the enviorment file like
select * from yql.storage where name="your enviorment file SELECT KEY"
the secret defined in your enviorment file will still expose.
but not one know your SELECT KEY except yourself. so you never use the SELECT KEY everything will be safe.
Thus, use the EXECUTE KEY!!!! no one can know what happen inside your enviorment file.
env "store://0zaLUaPXLo4GWBb1koVqO6"; select * from github where CODE="code from oauth first step"
Fin
copy the at the bottom, request this url from you client side javascript code. That’s is, without expose client_secret
safely get access_token
from pure client side javascript.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。