I had implemented the code to received authorization code as described in this step:
https://developers.google.com/android-publisher/authorization#generating_a_refresh_token
We deployed this code to one server that has "https://..." domain and this works well. We can get the access_token, refresh_token...
But now we need to deploy the same code to a dev server that has no "https".
I created a new OAuth client id with redirect uri using the dev server (no https, the rest /api/v1/... is the same as the previous working server)
Now anytime I tried to go to this url and Allow access
https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher&response_type=code&access_type=offline&redirect_uri=http://dev_server/api/v1/...&client_id=dev_server_client_id
I got 401 Unauthorized.
I'm not sure why, but the only difference I can see is "https" vs "http".
Any idea why?
Thank you very much.
Actually I forgot to update the corresponding values in my code
const oauth2Client = new OAuth2(
config.googleApi.clientId,
config.googleApi.clientSecret,
config.googleApi.redirectUri // <= Especially this value
);
These values need to be updated to (beside values on google console).
I am trying to build a Ruby Daemon service to access the Office 365 rest API. It was recently made possible to do this via the OAuth 'client_credentials' flow, as detailed in this blog post: https://learn.microsoft.com/en-us/archive/blogs/exchangedev/building-daemon-or-service-apps-with-office-365-mail-calendar-and-contacts-apis-oauth2-client-credential-flow
I am struggling to generate a valid access token. The token endpoint returns me a JWT however when using this token I received a 401 with this message:
The access token is acquired using an authentication method that is too weak to allow access for this application. Presented auth strength was 1, required is 2
I understand that the client_credentials flow requires you to present a X.509 cert, unfortunately all the examples in the blog post are for C#.
I am using a generated self signed cert and private key to do a client assertion when requesting the token. I followed the steps in the blog post to generate the cert and update the manifest to use this cert.
This is the ruby code for reference:
def request_token
uri = URI.parse("https://login.windows.net/== TENANT-ID ==/oauth2/token?api-version=1.0")
https = Net::HTTP.new(uri.host, uri.port)
req = Net::HTTP::Post.new(uri.request_uri)
req.set_form_data(
:grant_type => 'client_credentials',
:redirect_uri => 'http://spready.dev',
:resource => 'https://outlook.office365.com/',
:client_id => '== Client ID ==',
:client_secret => '== Client secret =='
)
https.use_ssl = true
https.cert = client_cert
https.key = client_key
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
resp = https.start { |cx| cx.request(req) }
#access_token = JSON.parse(resp.body)
end
Obviously I have removed certain bits of information for security. Even though it is ruby you can see I am using my cert to validate the client using an SSL connection.
Here's some more infomation on the error:
"x-ms-diagnostics" => "2000010;
reason=\"The access token is acquired using an authentication method that is too weak to allow access for this application. Presented auth strength was 1, required is 2.\";
error_category=\"insufficient_auth_strength\"",
"x-diaginfo"=>"AM3PR01MB0662",
"x-beserver"=>"AM3PR01MB0662"
Any help would be appreciate.
Edit
For others looking to do something similar in Ruby here's a Gist of the code I use: https://gist.github.com/NGMarmaduke/a088943edbe4e703129d
The example uses a Rails environment but it should be fairly easy to strip out the Rails specific bits.
Remember to replace YOUR CLIENT ID, TENANT_ID and CERT_THUMBPRINT with the correct values and point the cert path and client key methods to the right file path.
Then you can do something like this:
mailbox = OfficeAPI.new("nick#test.com")
messages = mailbox.request_messages
Instead of a client_secret in your request body, you need a client_assertion. This is a bit more complex, but it's the reason you need that certificate.
Basically you need to build a JSON Web Token and sign it with your certificate using a SHA256 hash. The token is going to look something like this:
Header:
{
"alg": "RS256",
"x5t": "..." // THUMBPRINT of Cert
}
Payload:
{
"aud": "https:\\/\\/login.windows.net\\/<The logged in user's tenant ID>\\/oauth2\\/token",
"exp": 1423168488,
"iss": "YOUR CLIENT ID",
"jti": "SOME GUID YOU ASSIGN",
"nbf": 1423167888,
"sub": "YOUR CLIENT ID"
}
If you're still with me, you now need to base64-encode both pieces (separately), then concatenate them with a '.'. So now you should have:
base64_header.base64_payload
Now you take that string and sign it with your certificate, using a SHA256 hash. Then base64-encode the result of that, url-encode it, then append to the string, so now you have:
base64_header.base64_payload.base64_signature
Finally, include this in your POST to the token endpoint as the client_assertion parameter, and also include a client_assertion_type parameter set to "urn:ietf:params:oauth:client-assertion-type:jwt-bearer":
req.set_form_data(
:grant_type => 'client_credentials',
:redirect_uri => 'http://spready.dev',
:resource => 'https://outlook.office365.com/',
:client_id => '== Client ID ==',
:client_assertion_type => 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
:client_assertion => 'base64_header.base64_payload.base64_signature'
)
I hope that helps! This is all based on my research into how ADAL does it, and I haven't tested it myself in Ruby.
I just managed to get this working, so I thought I'd throw one more piece of advice into the mix. All the instruction articles out there say that you should add your certificate to the manifest file. I had trouble with that, but here is what I did that finally made it work:
In Azure, go to Settings > Management Certificates
Upload the public key as a .cer file (google around if you don't know how to convert it). This should be a binary file that your text editor barfs on.
Now that it's uploaded, Microsoft will give you the thumbprint. It's in the "Thumbprint" column. But, it's in hex, not base64. So, convert it like this:
# Hint: use your actual thumbprint, not this fake one
echo '5292850026FADB09700E7D6C1BCB1CD1F3270BCC' | xxd -r -p | base64
Finally, use this base64 encoded thumbprint as the value for x5t in the JSON header.
I added a function in HomeController on the git to demo how to request an access token by hand using client assertion w/o ADAL. It might be easier to port using this: https://github.com/mattleib/o365api-as-apponly-webapp/commit/12d5b6dc66055625683020576139f5771e6059e1
Just some additions: The audience claim in the assertion is the same as the endpoint you address with the token request. As Jason correctly identified, this is the token endpoint of AAD: https://login.windows.net/{the tenant you want an app token for}/oauth2/token. Also the nbf and exp are the time you created the assertion in unix epoche time, e.g. in .net you would do something like "WebConvert.EpocTime(DateTime.UtcNow)". For "not before" (nbf) maybe subtract a buffer for clock skew, e.g. 5 minutes; and for expires in (exp) add some time, e.g. 15 minutes (so the assertion remains valid for that time).
Here is a fiddler trace of a token request (raw):
POST https://login.windows.net/0e49ef1f-ca07-45f1-b4c0-ac9409d3e576/oauth2/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
client-request-id: a8108f88-275b-424d-ac28-f675aabe548e
return-client-request-id: true
x-client-SKU: .NET
x-client-Ver: 2.12.0.0
x-client-CPU: x64
x-client-OS: Microsoft Windows NT 6.2.9200.0
Host: login.windows.net
Content-Length: 983
Expect: 100-continue
Connection: Keep-Alive
resource=https%3A%2F%2Fgraph.windows.net%2F&client_id=f17bb8a5-2bef-4ad5-a83f-cd7113449fc2&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJhbGciOiJSUzI1NiIsIng1dCI6ImY4S2JVY0xtMnItS2s4b1Z3ZVZYTFU0NzhJcyJ9.eyJhdWQiOiJodHRwczpcL1wvbG9naW4ud2luZG93cy5uZXRcLzBlNDllZjFmLWNhMDctNDVmMS1iNGMwLWFjOTQwOWQzZTU3Nlwvb2F1dGgyXC90b2tlbiIsImV4cCI6MTQyMjk4NDMzNSwiaXNzIjoiZjE3YmI4YTUtMmJlZi00YWQ1LWE4M2YtY2Q3MTEzNDQ5ZmMyIiwianRpIjoiZTI3OTA5YTctZGYwMC00NjBhLTlmZjctOGZkNDExOWVmNTYzIiwibmJmIjoxNDIyOTgzNzM1LCJzdWIiOiJmMTdiYjhhNS0yYmVmLTRhZDUtYTgzZi1jZDcxMTM0NDlmYzIifQ.g9bo4-lxpNJ4kEOMuQxODU-5iakwSVIzyRQEPLdbpuNn_XD4lcvt2yBIWT12EQaUVKkMyqFrDiIh4Oav565-Po7HfhmSPF3URXVj8Kx5lx17Zh0nWiaNkRXEi1vhwswsfjm1o-8B8LGUJTtT6JXTognrueuSL1aEE_-4qSG1y74aoc949Un1pQCjwuBtao4vs4CPJLu9Y9mVbirVRRtiIfxkUMmzf6yfMtuhugoGmrvUYntUo4x6N2fu4LxGjuIs7czyrMMAmDRo-XK4sAhDo5uof10HKb8ETEU8mhObwNZcz86MYHWbZm3Z_HDOwzC9kA_tp6hWqmlJ3c-gLg5VXA&grant_type=client_credentials
Hope this helps!
Good luck!
Matthias
I have a simple problem that is getting me stuck. I have been following this yahoo documentation Yahoo OAuth 2.0 Guide . I have been able to generate authorization URL and even get the authorization code.(that is upto Step 3).
But now I am stuck in step 4: Exchange authorization code for Access Token. I am also using this StackOverflow question Yahoo API with Ruby on Rails and OAUTH2. This is my code(I'm using sinatra):
get '/yahoo/contacts/oauth2callback' do
client = OAuth2::Client.new($consumer_id, $consumer_secret, site: $yahoo_base_url, authorize_url: '/oauth2/request_auth', token_url: '/oauth2/get_token')
code = params[:code] if params[:code]
puts "Code: #{code}"
# token = client.auth_code.get_token(code, redirect_uri: $yahoo_redirect_url, headers: { "Authorization" => Basic })
token = client.auth_code.get_token(code, redirect_uri: $yahoo_redirect_url)
puts "THIS IS THE NEW TOKEN NOW: #{token}"
end
the variable used include:
# for yahoo application
$consumer_id = "dj0yJmk9Q1RKU2x2NTY3WWVxJmQ9WVdrOU1YWnRUV2cyTXpBbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD1fth--"
$consumer_secret = "my_secret"
$yahoo_redirect_url = "http://localhost:4567/yahoo/contacts/oauth2callback"
What What is causing the error? Because the error source is this line.
token = client.auth_code.get_token(code, redirect_uri: $yahoo_redirect_url)
what i'm I doing wrong?
Update: I had written the error at the title, and it seems many people can't see it.
the error is
OAuth2::Error invalid_request: {“error”:“invalid_request”}
file: client.rb location: request line: 113
the returned url is looks like this:
http://localhost:4567/yahoo/contacts/oauth2callback?code=bck5tkm.
Where the code being taken is bck5tkm
Assuming you use the intridea OAuth 2.0 client (https://github.com/intridea/oauth2), you may be bumping in to a bug:
https://github.com/intridea/oauth2/pull/192
meaning that Yahoo refuses to permit client credentials in the request body. The pull request has not been merged yet so you'd need to apply that to your own code (or find another gem that works).
You may be using an expired or already used code(can be used just once). Or you have supplied not valid credentials in the HTTP Basic Authorization header on the POST request.
I'm trying to use basic authentication in Github api. I wrote something like this:
require 'httpclient'
request = HTTPClient.new
request.set_basic_auth("http://api.github.com/authorizations", "my_username", "my_password")
request.get "http://api.github.com/user/repos"
and expect it returns the repos of a user. However, it keeps throwing an error:
Connection refused - connect(2) for "api.github.com" port 80 (Errno::ECONNREFUSED)
I know there are a whole bunch of gems like github, octokit that do the stuff for users. I want to try it myself. Does anyone know how do I authenticate with a simple http request in Ruby?
You need to make an HTTPS request instead of HTTP. Authentication always needs to use SSL.
You are also using the wrong URL's. As per their docs (https://developer.github.com/v3/auth/#basic-authentication) you need to set your basic authentication to the following path:
https://api.github.com/user
And make your repo request at:
"https://api.github.com/users/<USERNAME>/repos"
So your request would look something like
request = HTTPClient.new
request.set_basic_auth("https://api.github.com/user", "my_username", "my_password")
request.get "https://api.github.com/users/<USERNAME>/repos"
I suggest taking a look at the documentation that I linked to above, and make your first attempt by using curl requests, as they offer more information to help you debug.
Context: I'm trying to interact with Twitter via JSON and no libraries as i'm practicing to interact with a newly released receipt printer(themprinter.com) which has no helper libraries. I need to OAuth with the printer then make the appropriate calls to register my device, print, verify online/offline status etc.
I've successfully authenticated with Twitter via OmniAuth's Twitter Gem. I can pull all the data from the Authentication Hash here - https://github.com/arunagw/omniauth-twitter
...now what? I want to be able to make a JSON call with my OAuth credentials to Twitter and pull my timeline or any other such data. Can anyone provide any sample code that will allow me a starting point to tinker with and work off of?
Twitter provides REST API. Here's how you might create a GET REST request
request = Net::HTTP::Get.new(url, initheader = header)
http_request = Net::HTTP.new(host, port)
response = http_request.start {|http| http.request(request)}
here's an example of the request URL:
https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=twitterapi&count=2