Why should I transmit `client_secret` to obtain an `access_token`?
In order to obtain an access_token from Facebook, you have to transmit your app_id
, the code
you receive after the authorize request, and your app's secret_key
.
Why would 开发者_运维技巧I EVER transmit my secret key? This seems blatantly insecure. Is this a requirement of the OAuth 2.0 spec?
As a related question, why would I need to transmit an app_id
when my request is already signed with my consumer_key
?
I've got a working app, I just don't understand these requirements.
This is a requirement of the OAuth 2.0 spec, section 4.1.3.
If the client type is confidential or was issued client credentials (or assigned other authentication requirements), the client MUST authenticate with the authorization server as described in Section 3.2.1
And section 3.2.1 refers to section 2.3. Specifically, section 2.3.1 says:
Alternatively, the authorization server MAY allow including the client credentials in the request body using the following parameters:
client_id
REQUIRED. The client identifier issued to the client during
the registration process described by Section 2.2.
client_secret
REQUIRED. The client secret. The client MAY omit the
parameter if the client secret is an empty string.
There are indeed other ways OAuth 2.0 offers but by choosing this approach, Facebook is well within the spec. Now why Facebook opted for this approach, only Facebook can probably answer.
Beside being a requirement of Oauth2, the client_secret needs to be used in this step to verify you are indeed who you claim.
It all boils down to why the process is like it is...
The 'code' you get back from the first request is pretty weak from a security standpoint on it's own. It could hijacked on it's way back to you in the redirect link, which I've seen frequently go to landing pages without SSL protection. Even if you're 100% HTTPS thoughout your site, everything's not fully safe. Someone could find the code from looking at the request URLs which get logged inside your web server's access logs.
Even if you've got the tightest security environment this side of Buckingham Palace controlling access to you servers, if you've been riding the tech rodeo more than a few years, you know someone's going at some point 'archive' your logs somewhere less-than-ideally secure. Probably on a USB key they left behind at starbucks...
Nothing can be don't to avoid this if you're using a server side API flow. Unlike Javascript running inside the client browser, you can't have the temp code added after the hash to prevent it from being logged, because browser clients don't send anything past the hash mark with the request. JS can intercept the redirect Url, and parse out stuff after the Hash tag, that's why there is JS Oauth2 flow that simply returns the access_token with out the additional intermediary code song and dance. No Client_Secret need on the JS side either, which is good as it's generally frown upon when you put passwords and secret keys inside javascript.
Now, to prevent this intermediary code from being used by a bad guy to obtain an access token, the Client_ID and Client_Secret is sent along so the API server can authenticate you're the who you claim to be and you have the authorization to redeem the code for an access_token. Nothing beats a shared secret!
Since the code has a very short window of use before it expires--basically meant for you to redeem it for an access_token immediate--the danger of someone stealing code and trying to brute force a Client_Secret isn't too likely.
The combination of a short window of use and the client_secret (over ssl of course) provides a which you later exchange with you client credentials
Notice the words.... NOT RECOMMENDED.
2.3.1. Client Password
Clients in possession of a client password MAY use the HTTP Basic authentication scheme as defined in [RFC2617] to authenticate with the authorization server. The client identifier is encoded using the "application/x-www-form-urlencoded" encoding algorithm per Appendix B, and the encoded value is used as the username; the client password is encoded using the same algorithm and used as the password. The authorization server MUST support the HTTP Basic authentication scheme for authenticating clients that were issued a client password.
For example (with extra line breaks for display purposes only):
Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3
Alternatively, the authorization server MAY support including the client credentials in the request-body using the following parameters:
client_id REQUIRED. The client identifier issued to the client during the registration process described by Section 2.2.
client_secret REQUIRED. The client secret. The client MAY omit the parameter if the client secret is an empty string.
Including the client credentials in the request-body using the two parameters is NOT RECOMMENDED and SHOULD be limited to clients unable to directly utilize the HTTP Basic authentication scheme (or other password-based HTTP authentication schemes). The parameters can only be transmitted in the request-body and MUST NOT be included in the request URI.
For example, a request to refresh an access token (Section 6) using the body parameters (with extra line breaks for display purposes only):
POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
&client_id=s6BhdRkqt3&client_secret=7Fjfp0ZBr1KtDRbnfVdmIw
The authorization server MUST require the use of TLS as described in Section 1.6 when sending requests using password authentication.
Since this client authentication method involves a password, the authorization server MUST protect any endpoint utilizing it against brute force attacks.
精彩评论