I think it’s not for me alone that I’m extremely fed up with resources requiring registration on every occasion and without. With the obligatory captcha, which is correctly entered only from the fifth time, with confirmation by e-mail, which will definitely fall into spam and then - only in a day. To invent a new login-password pair every time will be forgotten, it is not safe to enter the same thing on all sites. In places, they roll pairs of the form “qwerty: qwerty” or “login: password”, but, alas, not everywhere. I'm tired. Do not count how many times I, seeing the inscription "only a registered user can ****", just crooked and closed the tab, so that I never go to this site again. Do resource managers themselves do not understand this?
But OAuth technology is already 6 years old, and 90% of the Internet audience has an account on at least one of the resources that support OAuth. So why there is no “Login through” button on every resource? I installed the survey on my site

those. I voted a little (not all of my users have their own website with registration), but it’s enough to have the idea to write this article, in the hope that there will be more sites that use OAuth for authorization. Because:
- This is not a complicated technology. I dare to hope that everyone who has found the strength to read the article to the end will be able to independently bolt OAuth to his site in 1-2 days.
- OAuth is based on HTTP. Most service providers do not even require digital signatures, i.e., apart from the ability to create GET and POST requests, nothing is needed, and the simplicity of the protocol allows an OAuth client to be written “on the knee” in just an hour. Without any special libraries.
- So they will register with you! Simply use their login password on another site. Service providers do not provide any specific user profile required on your site? So request this characteristic at the first visit and all business. For the rest - the user logged in through OAuth is no different from registered in the usual way.
- I did not intend to describe in detail the OAuth protocol and its capabilities. This is all written repeatedly, for example, here and here . I want to give examples of the practical implementation of OAuth for the most common social networks of RuNet without being tied to a specific language.
- As for the 7% who do not need OAuth - if 93 out of a hundred administrators who have read this post implement OAuth on their site, I will be more than satisfied :)
Why OAuth, not OpenID?
Because OpenID is practically useless for those purposes for which it is declared. This is purely my opinion, but it does not rely on empty space.
First, OpenIDs are used mainly by geeks, the percentage of which on the Internet is not so high as to rebuild their sites (with some exceptions, of course :)) Why is that? Because in order to get an OpenID account, you need to - get it. Log on to the OpenID server and take some action to get some rather obscure set of characters. Which, in spite of the complexity (for the simple user), must be remembered and entered on occasion, if the familiar icon picks up

. Well, what kind of casual user will do this? And with OAuth, everything is much simpler - a person sees the “Login with VKontakte” button, clicks, and ... already on the site with registered user rights. “Keep it simple,” the classic said, “and people will reach for you.” As the water looked.
Secondly, the possibilities of OAuth are far from exhausted by authentication and authorization. Having received a token in the process of authorization, it can be used to further integrate the capabilities of social networks into your resource - reading / writing posts, access to friendlt and wall, and much more.
Thirdly, OpenID is actively used by spammers and hackers. Frequently, the implementation of OpenID authentication on a resource is done without paying special attention to its known vulnerabilities - only by the description of the protocol on the OpenID provider or with the help of an unknown person and when the written library. For example, many sites do not require captcha input from incoming OpenID. And nothing prevents an attacker from raising his OpenID server, which will confirm any identifier and start spamming a trusting site with automatically generated identifiers. In addition, OpenID authentication, in essence, does not give any guarantees to the client. It only confirms that the requested user is actually registered on one of the OpenID servers, and that’s all. Mechanisms for obtaining additional information about the user (email, name, age) are available, but few are supported. You can, of course, in violation of the ideas of OpenID, analyze the identifier and trust only certain OpenID providers (for example, the same social programs). But the point is, if almost all of them (with the exception of LiveJournal, but he doesn’t tell anything about the user via OpenID) support OAuth, which allows you to get much more information? So from all of my sites I generally removed support for OpenID.
Why OAuth, not the login via widget?
No problems. If you are satisfied with the functionality, design and security level of the widget - then it is actually much easier to stick it into the code - you can not read further.
')
How it works.
If anyone is interested in all the details, then see the links above. And in short - like this:
- You go to the service provider XXX, register your website there, get a client code and a secret code.
- By pressing the button on your site “login through XXX”, requests are exchanged with the XXX server, the user is redirected to XXX to enter a password, login and confirmation of data transfer to your website and receive a token, through which XXX server can request additional information about the user . Specificity depends on the service provider’s OAuth implementation — supported protocol version, supported streams, etc.
- Using the received token from the XXX server, you can get the name, email, date of birth, avatar and other information that is usually required at registration. After that, you can call the standard function to add a new user.
Why is raw HTTP rather than chunks of code using the OAuth library?
Because I was tormented by the order, pulling out this most raw HTTP often from pieces of code that illustrate the use of a particular library. The specific implementation of OAuth on each server has its own subtleties, to which even the most flexible library can save. In addition, many web languages, libraries - even more, to give examples of everything is simply unrealistic. And raw HTTP (in the presence of brains) is enough to use any library. What can not be said about the opposite case.
Practical recommendations for implementation
Of course, first you need to register on the social network, activate your account, and so on. Do not rush. Some servers do not immediately correctly process requests from newly registered OAuth clients. Here I have painted only successful streams, you should not forget about error handling. Also, I almost did not pay attention to security aspects - this is a topic for a separate article. At a minimum, wherever you can pass a unique parameter to the callback-url for each user, this should be done (the main callback address should remain unchanged, and only the parameter should change, otherwise the server will not miss the request. Pay particular attention to this if you should be mod_rewrite), and use the state parameter to transfer additional data to the callback script (where this parameter is supported). I have so far left all this behind the brackets.
In contact with
1. Come
here . Type - "Website". Enter the base domain and site address. On the settings page, we get client_id (application ID) and secret_key (secure key).

2. We stick in the code the type button
<a href="http://oauth.vk.com/authorize?client_id={client_id}&redirect_uri=mysite.com/vklogin&response_type=code" title=" "> </a>
response_type=code, token? response_type=token. vklogin? , , .
3. vklogin?
3.1. vklogin get- ( ) .
http://mysite.com/vklogin?code=7a6fa4dff77a228eeda56603b8f53806c883f011c40b72630bb50df056f6479e52a
http://mysite.com/vklogin?error=invalid_request&error_description=Invalid+display+parameter
, code,
3.2. https- (
POST, GET. , ) :
GET https://oauth.vk.com/access_token?client_id={client_id}&client_secret={secret_key}& code=7a6fa4dff77a228eeda56603b8f53806c883f011c40b72630bb50df056f6479e52a//
3.3. . , 200 OK .
JSON, access_token user_id. ( ) GET — users.get API :
GET https://api.vk.com/method/users.get?uids={user_id}&fields=uid,first_name,last_name,nickname,screen_name,sex,bdate,city,country,timezone,photo&access_token={access_token}
3.4. ( ) - JSON . . — utf8, — , .
, , . API .
1.
.
OAuth . -. , , . , . «», ...
2. , , .

. «» , client_id(Application ID), public_key( ) secret_key( )
3. :
<a href="http://www.odnoklassniki.ru/oauth/authorize?client_id={client_id}&response_type=code&redirect_uri=http://mysite.com/oklogin" title=""> </a>
4. oklogin
3.1. code.
3.2.
POST :
http://api.odnoklassniki.ru/oauth/token.do
:
code={code}&redirect_uri=http://mysite.com/oklogin&grant_type=authorization_code&client_id={client_id}&client_secret={secret_key}
3.3.
JSON , access_token. GET-:
GET http://api.odnoklassniki.ru/fb.do?method=users.getCurrentUser&access_token={access_token}&application_key={public_key}&sig={sign}
sign — md5-
sign=hex_md5('application_key={public_key}method=users.getCurrentUser'+hex_md5({access_token}+{secret_key}))
-, .
3.4. JSON- , , , . — utf8;
users.getCurrentUser . API . , , .
Facebook
1.
« ». App Domains () (). «Website with Facebook Login» url . client_id (App ID) secret_key (App Secret).

«Auth Dialog» «Authenticated Referrals» «code» «Auth Token Parameter».

2. :
https://www.facebook.com/dialog/oauth?client_id={client_id}&redirect_uri=mysite.com/fblogin&response_type=code
3.fblogin.
3.1. code.
3.2.
GETGET https://graph.facebook.com/oauth/access_token?client_id={client_id}&redirect_uri=http://mysite.com/fblogin&client_secret={client_secret}&code={code}
3.3.
(param1=value1¶m2=value2). access_token, GET-:
GET https://graph.facebook.com/me?access_token={access_token}
3.4.
JSON- , , , .
— NFC ( \u0410\u0401\u0419)
API ( ) .
Twitter
1.
. , , -.

«Create my access token».
, . . ??? twitter - OAuth-. , ( Net::OAuth ) .1. OAuth 1.0 . « Twitter» ,
POST-https://api.twitter.com/oauth/request_token
:
Authorization:OAuth oauth_callback=«http%3A%2F%2Fmysite.com%2Ftwlogin», oauth_consumer_key="{consumer_key}", oauth_nonce="{nonce}", oauth_signature_method=«HMAC-SHA1», oauth_timestamp="{time}", oauth_signature="{sign}", oauth_version=«1.0»
oauth_callback — escape-uri - ;
consumer_key ;
nonce — base64 , , , 32, , ;
time — unix- ( , , «» , « »);
sign — HMAC-SHA1 .
nonce — .1.1. . , escape-, '&'. :
{_}&{escape-uri }&{escape- }
, escape-
. , ,
:
str='POST&https%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&oauth_callback%3D{http%253A%252F%252Fmysite.com%252Ftwlogin}%26oauth_consumer_key%3D{consumer_key}%26oauth_nonce%3D{random base64 srting}%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D{time}%26oauth_version%3D1.0'
1.2. , hmac_sha1 (, , ) 64. - :
str1=hmac_sha1(str,Consumer_secret+'&'+OAuth_token_secret,64).
OAuth token secret- , , Consumer secret '&'. ( ) base_64 , escape-. . .
2. ,
oauth_token=XXXXX.
https://api.twitter.com/oauth/authenticate?oauth_token=XXXXX
3. twlogin, :
3.1. oauth_token oauth_verifier ( )
3.2. POST-
https://api.twitter.com/oauth/access_token
Authorization:OAuth oauth_consumer_key="{consumer_key}", oauth_nonce="{random base64 string}", oauth_signature_method=«HMAC-SHA1», oauth_timestamp="{time}", oauth_signature="{sign}", oauth_token="{oauth_token}", oauth_version=«1.0»'
,
:
oauth_verifier={oauth_verifier}
oauth_token oauth_verifier , , sign
str='POST&https%3A%2F%2Fapi.twitter.com%2Foauth%2Faccess_token&oauth_consumer_key%3D{consumer_key}%26oauth_nonce%3D{random base64 string}%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D{time}%26oauth_token%3D{oauth_token}%26oauth_verifier%3D{oauth_verifier}%26oauth_version%3D1.0';
3.3. , . GET-
GET https://api.twitter.com/1/users/lookup.json?user_id={user_id}
Authorization:OAuth oauth_consumer_key="{consumer_key}", oauth_nonce="{random base64 string}", oauth_signature_method=«HMAC-SHA1», oauth_timestamp="{time}", oauth_signature="{sign}", oauth_token="{oauth_token}", oauth_version=«1.0»'
user_id oauth_token ,
str='GET&https%3A%2F%2Fapi.twitter.com%2F1%2Flookup.json&oauth_consumer_key%3D{consumer_key}%26oauth_nonce%3D{random base64 string}%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D{time}%26oauth_token%3D{oauth_token}%26oauth_version%3D1.0%26user_id%3D{user_id}'
, , oauth_token_secret:
str1=hmac_sha1(str,Consumer_secret+'&'+OAuth_token_secret,64)
3.4.
JSON- , , .
API .
Mail.ru ()
1.
. , receiver.html, . receiver.html — , JS API, , , , receiver.html , . client_id (ID) secret_key ( ).

2. :
<a href="https://connect.mail.ru/oauth/authorize?client_id={client_id}&response_type=code&redirect_uri=http%3A%2F%2Fmysite.com%2Fmmlogin"> MailRu</a>
3. mmlogin
3.1. code.
3.2.
POST :
https://connect.mail.ru/oauth/token
:
client_id={client_id}&client_secret={secret_key}&grant_type=authorization_code&code={code}&redirect_uri=http://mysite.com/mmlogin
3.3.
JSON , access_token. GET-:
GET http://www.appsmail.ru/platform/api?method=users.getInfo&secure=1&app_id={client_id}&session_key={access_token}&sig={sign}
sign — md5-
sign=hex_md5('app_id={client_id}method=users.getInfosecure=1session_key={access_token}{secret_key}')
hex string.
3.4. JSON- , , , . — utf8;
API ( ) .
1.
. .. .

client_id(Id ) secret_key( ).

2. :
<a href="https://oauth.yandex.ru/authorize?response_type=code&client_id={client_id}" title=""> </a>
3. yalogin
3.1. code.
3.2.
POST :
https://oauth.yandex.ru/token
:
grant_type=authorization_code&code={code}&client_id={client_id}&client_secret={secret_key}
3.3.
JSON , access_token. GET-:
GET https://login.yandex.ru/info?format=json&oauth_token={access_token}
3.4. JSON- , , email, . (, . . . — c, — « » .) — NFC-. , json- . , ,
email : xxx@ttt.com
. , RFC JSON , — - .
API yandex.login .
Google
1.
. . API access «Create an OAuth2 client ID».

client_id(Client ID) secret_key(Client Secret).

2. :
<a href="https://accounts.google.com/o/oauth2/auth?redirect_uri=http%3A%2F%2Fmysite.com%2Fgglogin&response_type=code&client_id={client_id}&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile" title=" Google"> Google</a>
3. gglogin
3.1. code.
3.2.
POST :
https://accounts.google.com/o/oauth2/token
:
code={code}&client_id={client_id}&client_secret={secret_key}&redirect_uri=http://mysite.com/gglogin&grant_type=authorization_code
Content-type:application/x-www-form-urlencoded
3.3.
JSON , access_token. GET-:
GET https://www.googleapis.com/oauth2/v1/userinfo?access_token={access_token}
3.4. JSON- .
API - .. , .
, , OAuth. , , .
perl, , OAuth — . — .