Google OAUTH using django get access token - oauth

I'm struggling to retrieve access token using django.
I want to get access token from users using oAuth.
This is what I have setup so far.
class GoogleExhangeViewSet(viewsets.ViewSet):
queryset = User.objects.all()
#list_route(
methods=["GET"])
def auth(self,request,pk=None):
client_id = ''
client_secret = ''
flow = OAuth2WebServerFlow(client_id=client_id,
client_secret=client_secret,
scope='https://www.googleapis.com/auth/calendar',
redirect_uri='http://localhost:8001/api/googleAuth/complete')
auth_uri = flow.step1_get_authorize_url()
return HttpResponseRedirect(auth_uri)
def complete(self, request, pk=None):
client_id = ''
client_secret = ''
host = Site.objects.get_current().name
flow = OAuth2WebServerFlow(client_id=client_id,
client_secret=client_secret,
scope='https://www.googleapis.com/auth/calendar',
redirect_uri='http://localhost')
credentials = flow.step2_exchange(request.GET.get('code'))
return Response(status=200,data=credentials.access_token)
under urls.py I have
api_router.register(r'api/googleAuth', GoogleExhangeViewSet)
This is the error I get with the following code

As seen in your error, you are encountering a redirect_uri_mismatchBad Request if you are using a wrong redirect uri. From this link, the redirect_uri_mismatch will be thrown if it was not matched between auth and token requests.
Additional references:
Google oAuth2 redirect_uri_mismatch in token access
Google OAuth 2.0 redirect_uri_mismatch error
Here's a tutorial if you want to use an Access Token to authenticate users against Django’s authentication system.
You need a fully-functional OAuth2 provider which is able to release access tokens: just follow the steps in the part 1 of the tutorial. To enable OAuth2 token authentication you need a middleware that checks for tokens inside requests and a custom authentication backend which takes care of token verification.

Related

What auth flow to use with spa and service account msal

There's so many different flows in the Microsoft docs that I have no clue what one is needed for me. I am using React and Python. (I understand node, so if someone explains using node/express its fine)
What user should see:
A page with a button to login, nav is there but wont work till logged in. The login creates a popup to sign in with Microsoft account. Once signed in, the user will be able to use nav to see dynamics information.
What I am trying to do:
This app needs to sign in a user and obtain the users email through 'https://graph.microsoft.com/v1.0/me'.(no client secrets needed) Then I need to send that email in this request;
(The tenant == {company}.crm.dynamics.com.)
allInfo = requests.get(
f'https://{TENANT}api/data/v9.0/company_partneruserses?$filter=company_email eq \'{email}\'', headers=headers).json()
This backend request needs to have a client secret to obtain the information. So I believe my backend also needs to be logged on to a service account. I believe I need to get a token for my backend to make requests on behalf of the service account.
What I have:
I have a React frontend that is signing a user in and calling 'https://graph.microsoft.com/v1.0/me' correctly and getting that email. Once I get the email, I am sending it to my backend.
Now I have no clue how to proceed and have tried many things.
What I have tried for backend:
Attempt 1: I get a token but error: {'error': {'code': '0x80072560', 'message': 'The user is not a member of the organization.'}}. Problem is, this id is the Azure AD ID. It should def work
#app.route('/dynToken', methods=['POST'])
def get_dyn_token():
req = request.get_json()
partnerEmail = req['partnerEmail']
token = req['accessToken']
body = {
"client_id": microsoft_client_id,
"client_secret": client_secret,
"grant_type": "client_credentials",
"scope": SCOPE_DYN,
}
TENANTID = '{hash here}'
res = requests.post(
f'https://login.microsoftonline.com/{TENANTID}/oauth2/v2.0/token', data=body).json()
dyn_token = res['access_token']
headers = {
"Prefer": "odata.include-annotations=\"*\"",
"content-type": "application/json; odata.metadata=full",
"Authorization": f"Bearer {dyn_token}"
}
try:
allInfo = requests.get(
f'https://{TENANT}api/data/v9.0/company_partneruserses?$filter=company_email eq \'{email}\'', headers=headers).json()
print(allInfo)
Attempt 2:
Same code but instead of f'https://login.microsoftonline.com/{TENANTID}/oauth2/v2.0/token' its
f'https://login.microsoftonline.com/common/oauth2/v2.0/token'. Error: An exception occurred: [Errno Expecting value] : 0. Because it returns an empty string.
Now I don't know if I am even on the right path or where to go. I know the routes work themselves if the token is correct. I used only SSR with no react and these routes work. But I need the React to be there too. I just don't know what flow to use here to get what I need. The docs make it easy for /me route to work. But the {company}crm.dynamics.com docs don't really provide what I am trying to do.
Additional info after comment:
What 'f'https://{TENANT}api/data/v9.0/company_partneruserses?$filter=company_email eq '{email}'', headers=headers" is trying to get are API keys. Full code :
try:
allInfo = requests.get(
f'https://{TENANT}api/data/v9.0/company_partneruserses?$filter=company_email eq \'{email}\'', headers=headers).json()
partner_value = allInfo['value'][0]['_company_partner_value']
response = requests.get(
f'https://{TENANT}api/data/v9.0/company_partnerses({partner_value})', headers=headers).json()
return {'key': response['company_apikey'], 'secret': response['company_apisecret']}
Then once it has the keys:
def api_authentication(apikey, apisecret):
headers = get_headers() #<-- same headers as above with using dyn_token
response = requests.get(
f'https://{TENANT}api/data/v9.0/company_partnerses?$filter=company_apikey eq \'{apikey}\' and company_apisecret eq \'{apisecret}\'&$select=company_apikey,company_apisecret,_company_account_value,_company_primarycontact_value,blahblah_unassignedhours,company_reporturl', headers=headers).json()
return response
Afterwards I am able to get all the information I am looking for to send back to my frontend for the client to see. (By making multiple request to crm with these keys)
The client_credentials grant that you are using should work, provided the CRM trusts the token issued to the client (your python backend). Please use MSAL library instead of hand crafting the token request. It will save you time and eliminate errors.

LinkedIn API Get Access Token Failed

We are trying to implement the LinkedIn API authentication module based on: https://learn.microsoft.com/en-us/linkedin/shared/authentication/authorization-code-flow?context=linkedin/context.
We have the redirect url for the application setup as our company's main page (https://www.{site}.com) and we are able to get the auth code from the redirect URL. However, it gives us 401 error below when exchange for access token:
b'{"error":"invalid_request","error_description":"Unable to retrieve
access token: authorization code not found"}'
The weird thing is, it works and we are able to exchange the code for access token if we switch the redirect url to a different site like https://www.example.com in the API Console. Below is the Py3 code we use:
from requests_oauthlib import OAuth2Session
from requests_oauthlib.compliance_fixes import linkedin_compliance_fix
# Credentials and redirect uri you get from registering a new application
client_id = 'client_id'
client_secret = 'client_secret'
redirect_url = 'redirect_url'
# OAuth endpoints given in the LinkedIn API documentation (check for updates)
authorization_base_url = 'https://www.linkedin.com/oauth/v2/authorization'
token_url = 'https://www.linkedin.com/oauth/v2/accessToken'
# Authorized Redirect URL (from LinkedIn config)
o2_session = OAuth2Session(client_id=client_id, redirect_uri=redirect_url, scope=['rw_ads', 'r_ads_reporting'])
linkedin = linkedin_compliance_fix(o2_session)
# Redirect user to LinkedIn for authorization
authorization_url, state = linkedin.authorization_url(authorization_base_url)
print('Please go here and authorize,', authorization_url)
# Get the authorization verifier code from the callback url
redirect_response = input('Paste the full redirect URL here:')
linkedin.fetch_token(token_url, include_client_id=client_id, client_secret=client_secret, authorization_response=redirect_response)
token = linkedin.access_token
Understood that the auth code has short life span, so tried both redirect URL seconds after the code is post back to the URL. Can anyone think of any reason could cause this weird different behaviors for different redirect URLs.

Ruby OAuth with Salesforce not getting refresh_token

I can't seem to get a refresh_token whenever I'm authorized, I've tried setting headers, kind of like how it would be done with google oauth, but not luck. Here's my process:
Using oauth2 gem
Instantiate client
client = OAuth2::Client.new(
salesforce_app_key,
salesforce_secret_key,
site: 'https://login.salesforce.com/services/oauth2/',
authorize_url: 'https://login.salesforce.com/services/oauth2/authorize',
token_url: 'https://login.salesforce.com/services/oauth2/token',
raise_errors: false
)
Authorize connection
auth = client.auth_code.authorize_url(
redirect_uri: 'https://my_app_callback.com/oauth/authorize'
)
Fetch token
token = client.auth_code.get_token(
code,
redirect_uri: 'https://my_app_callback.com/oauth/authorize'
)
From this point, I have the connection set, but when I do token.refresh_token I get a nil value.
By using:
access_token = OAuth2::AccessToken.new(oauth, token)
The session was reestablished successfully. It's in the docs, but not written in a way I could uderstand it's used to reauthenticate.

Issue exchanging LInkedIn javascript token to rest oauth token

I am using the article located at https://developer-programs.linkedin.com/documents/exchange-jsapi-tokens-rest-api-oauth-tokens to exchange my Javascript access token to a REST OAuth token.
After following the directions here, no matter what I seem to do, I only get a 400 Bad Request response back.
The flow I use for Facebook and want to recreate with LinkedIn is; front end authenticates to LinkedIn and passes an access token to my API, the API then gets all necessary user information and passes my own bearer token back to the client, et voila.
Unfortunately LinkedIn doesn't play so nicely with this, and I need to convert my token to an OAuth token from its Javascript token.
I pass the cookie LinkedIn gives me to my API, it looks something like the below (where OAuthBase is http://oauth.googlecode.com/svn/code/csharp/OAuthBase.cs)
access_token: "oxmKI9aU4RCfksdegZ3obZGHK-vo6Q4-4FSQk"
member_id: "AmjWCF7ExN"
signature: "t8KEbLjJ+r6uM42tUwfJm5yWp70="
signature_method: "HMAC-SHA1"
signature_order: ["access_token","member_id"]
signature_version: "1"
I then am attempting to make a call to https://api.linkedin.com/uas/oauth/accessToken to do the actual exchange. My code for this is:
public async Task<IHttpActionResult> ConvertLinkedInToken(LinkedInCovertTokenObject val)
{
string normalizeduri;
string normalizedparams;
OAuthBase o = new OAuthBase();
string signature = o.GenerateSignature(new Uri("https://api.linkedin.com/uas/oauth/accessToken"), Startup.linkedInAuthOptions.ClientId, Startup.linkedInAuthOptions.ClientSecret, val.access_token, null, "POST", o.GenerateTimeStamp(), o.GenerateNonce(), out normalizeduri, out normalizedparams);
var client = new HttpClient();
var uri = new Uri("https://api.linkedin.com/uas/oauth/accessToken?" +
"oauth_consumer_key=" + Startup.linkedInAuthOptions.ClientId +
"&xoauth_oauth2_access_token=" + val.access_token +
"&signature_method=HMAC-SHA1" +
"&signature=" + signature
);
var response = await client.GetAsync(uri);
return Ok();
}
No matter how I play around all I get back from LinkedIn is a 400 Bad Request without any other useful information.
1) How can I convert LinkedIn JS token to Rest OAuth token in my c# api
This is how I achieved that:
On the frontend:
IN.User.authorize(function(){
// here you can find oauth token
var oauth_token = IN.ENV.auth.oauth_token;
// send this token to your API endpoint
});
On your API (curl example), of course replace OAUTH_TOKEN with token received on the frontend.
curl -X GET \
'https://api.linkedin.com/v1/people/~:
(id,firstName,lastName,siteStandardProfileRequest,picture-url,email-
address)?format=json' \
-H 'oauth_token: OAUTH_TOKEN'
You are looking at old documentation from LinkedIn. Starting from 12th May, LinkedIn has started rolling out new changes in their API which includes authentication. In my knowledge, LinkedIn is not using OAuth anymore, and you need OAuth2.0 henceforth for authentication. You should check this link for more information:
https://developer.linkedin.com/docs/signin-with-linkedin

Twitter 3-legged authorization in Ruby

I am trying my hand ruby on rails. Mostly I have written code in Sinatra. Anyway this question may not have to do anything with framework. And this question may sound a very novice question. I am playing with Twitter 1.1 APIs and OAuth first time.
I have created an app XYZ and registered it with Twitter. I got XYZ's consumer key i.e., CONSUMER_KEY and consumer secret i.e. CONSUMER_SECRET. I also got XYZ's own access token i.e ACCESS_TOKEN and access secret i.e. ACCESS_SECRET
XYZ application type: Read, Write and Access direct messages
XYZ callback URL: http://www.mysite.com/cback
And I have checked: Allow this application to be used to Sign in with Twitter
What I am trying to do is very simple:
1) Users come to my website and click a link Link your twitter account (not signin with twitter)
2) That opens twitter popup where user grants permission to XYZ to perform actions on his/her behalf
3) Once user permits and popup gets closed, XYZ app gets user's access token and secret and save in the database.
4) Then XYZ uses that user's token and secret to perform actions in future.
I may be moron that such work flow has been implemented on several thousands sites and Twitter API documentations explain this 3-legged authentication, still I am unable to figure it out.
I have read https://dev.twitter.com/docs/auth/3-legged-authorization and https://dev.twitter.com/docs/auth/implementing-sign-twitter Unfortunately no ruby code found on internet that explains with step by step example.
What link should be used to open twitter authentication page when user clicks Link your twitter account.
Can anyone here, write some pseudo code with my pseduo credential above to achieve my goal from beging till end of this work flow? Thanks.
UPDATE:
I started with requesting request token as
require 'oauth'
consumer = OAuth::Consumer.new(CONSUMER_KEY, CONSUMER_SECRET,
{ site: "https://twitter.com"})
request_token = consumer.get_request_token oauth_callback: 'http://www.mysite.com/tauth'
redirect_to request_token.authorize_url
I'm not familiar with ROR but here is the workflow of the OAuth 'dance' that you need to follow when the user clicks your button:
Obtain an unauthorized request token from Twitter by sending a
request to
POST https://api.twitter.com/oauth/request_token
signing the request using your consumer secret. This will be done in the background and
will be transparent to the user.
You will receive am oauth_token and oauth_token_secret back from
twitter.
Redirect the user to
https://api.twitter.com/oauth/authorize?oauth_token=[token_received_from_twitter]
using the oauth token value you received from Twitter in step 2.
When the user authorizes your app they will be redirected to your
callback url with oauth_token and oauth_verifier appended to the
url. i.e.
http://www.mysite.com/cback?oauth_token=NPcudxy0yU5T3tBzho7iCotZ3cnetKwcTIRlX0iwRl0&oauth_verifer=uw7NjWHT6OJ1MpJOXsHfNxoAhPKpgI8BlYDhxEjIBY
Convert the request token into an access token by sending a signed
request along with the oauth_verifier to
POST
https://api.twitter.com/oauth/access_token
signing your request
with your consumer secret and the token secret received in step 2.
If everything goes ok, you will receive a new oauth_token and
oauth_token_secret from Twitter. This is your access token for the
user.
Using the access token and secret received in step 6 you can make
Twitter api calls on behalf the the user by sending signed requests
to the appropriate api endpoints.
Hope you solved your problem by this time, but I built this sample Sign in with Twitter ruby web app that provide all explanation you need to do this integration. Below there's a class that implements all necessary methods with comments:
require "net/https"
require "simple_oauth"
# This class implements the requests that should
# be done to Twitter to be able to authenticate
# users with Twitter credentials
class TwitterSignIn
class << self
def configure
#oauth = YAML.load_file(TWITTER)
end
# See https://dev.twitter.com/docs/auth/implementing-sign-twitter (Step 1)
def request_token
# The request to get request tokens should only
# use consumer key and consumer secret, no token
# is necessary
response = TwitterSignIn.request(
:post,
"https://api.twitter.com/oauth/request_token",
{},
#oauth
)
obj = {}
vars = response.body.split("&").each do |v|
obj[v.split("=").first] = v.split("=").last
end
# oauth_token and oauth_token_secret should
# be stored in a database and will be used
# to retrieve user access tokens in next requests
db = Daybreak::DB.new DATABASE
db.lock { db[obj["oauth_token"]] = obj }
db.close
return obj["oauth_token"]
end
# See https://dev.twitter.com/docs/auth/implementing-sign-twitter (Step 2)
def authenticate_url(query)
# The redirection need to be done with oauth_token
# obtained in request_token request
"https://api.twitter.com/oauth/authenticate?oauth_token=" + query
end
# See https://dev.twitter.com/docs/auth/implementing-sign-twitter (Step 3)
def access_token(oauth_token, oauth_verifier)
# To request access token, you need to retrieve
# oauth_token and oauth_token_secret stored in
# database
db = Daybreak::DB.new DATABASE
if dbtoken = db[oauth_token]
# now the oauth signature variables should be
# your app consumer keys and secrets and also
# token key and token secret obtained in request_token
oauth = #oauth.dup
oauth[:token] = oauth_token
oauth[:token_secret] = dbtoken["oauth_token_secret"]
# oauth_verifier got in callback must
# to be passed as body param
response = TwitterSignIn.request(
:post,
"https://api.twitter.com/oauth/access_token",
{:oauth_verifier => oauth_verifier},
oauth
)
obj = {}
vars = response.body.split("&").each do |v|
obj[v.split("=").first] = v.split("=").last
end
# now the we got the access tokens, store it safely
# in database, you're going to use it later to
# access Twitter API in behalf of logged user
dbtoken["access_token"] = obj["oauth_token"]
dbtoken["access_token_secret"] = obj["oauth_token_secret"]
db.lock { db[oauth_token] = dbtoken }
else
oauth_token = nil
end
db.close
return oauth_token
end
# This is a sample Twitter API request to
# make usage of user Access Token
# See https://dev.twitter.com/docs/api/1.1/get/account/verify_credentials
def verify_credentials(oauth_token)
db = Daybreak::DB.new DATABASE
if dbtoken = db[oauth_token]
# see that now we use the app consumer variables
# plus user access token variables to sign the request
oauth = #oauth.dup
oauth[:token] = dbtoken["access_token"]
oauth[:token_secret] = dbtoken["access_token_secret"]
response = TwitterSignIn.request(
:get,
"https://api.twitter.com/1.1/account/verify_credentials.json",
{},
oauth
)
user = JSON.parse(response.body)
# Just saving user info to database
user.merge! dbtoken
db.lock { db[user["screen_name"]] = user }
result = user
else
result = nil
end
db.close
return result
end
# Generic request method used by methods above
def request(method, uri, params, oauth)
uri = URI.parse(uri.to_s)
# always use SSL, you are dealing with other users data
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
# uncomment line below for debug purposes
#http.set_debug_output($stdout)
req = (method == :post ? Net::HTTP::Post : Net::HTTP::Get).new(uri.request_uri)
req.body = params.to_a.map { |x| "#{x[0]}=#{x[1]}" }.join("&")
req["Host"] = "api.twitter.com"
# Oauth magic is done by simple_oauth gem.
# This gem is enable you to use any HTTP lib
# you want to connect in OAuth enabled APIs.
# It only creates the Authorization header value for you
# and you can assign it wherever you want
# See https://github.com/laserlemon/simple_oauth
req["Authorization"] = SimpleOAuth::Header.new(method, uri.to_s, params, oauth)
http.request(req)
end
end
end
More detailed explanation at:
https://github.com/lfcipriani/sign_in_with_twitter_sample

Resources