Getting notFound error after domain wide delegation - ruby-on-rails

I am trying to set up domain wide delegation with Google so I can have access to a workspace calendar. I've followed through the documentation and here is what I've got so far:
Service account for the app is set up
Google Calendar API is enabled for this account
Generated and saved JSON key
Added app's account Client ID to Security -> API Controls -> Domain-wide Delegation with correct scopes
App's service account:
Workspace:
And here is my simple Ruby code for retrieving a simple calendar event:
google_calendar_service = ::Google::Apis::CalendarV3::CalendarService.new
google_calendar_service.authorization ::Google::Auth::ServiceAccountCredentials.make_creds(json_key_io: File.open(PATH_TO_JSON_FILE), scope: MY_SCOPES)
google_calendars.get_event(owner_email, event_id)
Both owner_email and event_id are correct as I have a working code that uses OAuth2 and it can get the event as expected.
What am I missing?

You need to add the subject that you are going to delegate as. This needs to be the user on your domain which you want the service account to act on behalf of
Check the authorizer.sub line.
authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
json_key_io: StringIO.new(File.read AppConfig[:credentials_file]),
scope: AppConfig[:cal_scope]).dup
authorizer.sub = #person
authorizer.fetch_access_token!

Related

Authenticating docusign via Rails API (Omniauth + Devise) + JS Frontend

I'm trying to create an authentication flow using Auth Code Grant where I've added necessary omniauth strategy for Docusign to create /auth/docusign routes in Rails API only application.
Here are the steps followed
I'm issuing a request to the route from VueJS client.
window.open("http://localhost:4000/auth/docusign", "targetWindow", "width=350,height=250")
After user enters credentials and on successful login I'm calling the callback:
class SessionsController < Devise::SessionsController
def docusign
internal_destroy
#success = false
userinfo = request.env['omniauth.auth']
request_info = request.env['omniauth.params']
if userinfo
info = userinfo.info
cred = userinfo.credentials
user = User.find_by(email: info['email']) || User.find_by(id: session[:user_id])
if user
organization = user.organization
organization.organization_providers.where(provider_name: 'Docusign').destroy_all
OrganizationProvider.create(email: info['email'], token_expires_at: Time.at(cred['expires_at']), token_expires_at: Time.now, provider_name: 'Docusign', organization_id: organization.id, token: cred.token)
#success = true
end
end
render 'sessions/docusign'
end
end
I'd like to pass some params (which I'm accessing in the callback as request.env['omniauth.params']) for executing some backend tasks in the method.
When I try window.open("http://localhost:4000/auth/docusign?email='"+email+"'", "targetWindow", "width=350,height=250")
It says that the url doesn't match with any redirect urls
I have also tried passing in redirect_to('/auth/docusign', query: query) but on doing so, it doesn't open in a browser due to CORS.
I'm also trying to set it in session cookie, but since it's an API only server, I'm still working towards setting up cookie store.
Question
Which is the best way to achieve this? To pass some params in the callback and retrieve it.
Then the execution flow continues on the Rails server and the window serves a page with an appropriate response as per authentication status. However during this time, the client window which started the request is not aware of the authentication outcome.
Question
How can I communicate to the VueJS client that the authentication process is completed?
Question
Am I doing the above flow correctly or are there any better ways to achieve the same?
Thanks in advance
You need to log into your DocuSign Developer Account, Click on Admin and go on the left nav down to "API and Keys" where you can find the integration key you set. Did you set one?
If you did, you should find it and then add the redirectUri to the OAuth settings for that key (client ID in OAuth).
That is why DocuSign login tells you that the redirectURI doesn't match. You can add http://localhost:4000/auth to the list and that should work for your local env.
You cannot past custom variables on the redirectUri, it has to match exactly to the one you entered. If you need to pass values to it, there's a way to do that using state.
Here is how the URL should look, notice the &state= part of it:
https://account-d.docusign.com/oauth/auth?
response_type=code
&scope=YOUR_REQUESTED_SCOPES
&client_id=YOUR_INTEGRATION_KEY
&state=YOUR_CUSTOM_STATE
&redirect_uri=YOUR_REDIRECT_URI
&login_hint=YOUR_LOGIN_HINT
You can put whatever you want in there (URI encoded of course) and that value would come back to you when redirected back also with &state= parameter.
This solves the problem and allows you to pass arguments back to your redirect URI.

how to get the roles in access token: keycloak

what I am trying to do:
I have an app that takes in login credentials: username and password for a user. I have a rest api that internally calls the keycloak REST API: /auth/realms/realmname/protocol/openid-connect/token
and gets the access token for this user.
Now I am building another REST API to access a resource where I want to do the following:
doSomething(accesstoken, data)
{
a) call keycloak API to validate access token and get roles.
b) if role == manager, process(data)
c) else: return error msg.
}
Now, how do I do (a): validating the access token and getting the roles associated with it.
I know we can do: auth/realms/realmname/protocol/openid-connect/userinfo
but that only gives the details about the user like name, email, etc. but does not display any roles.
Here's an example I got:
{
"name": "test user",
"sub": "e2bad34d-a1a9-4d70-ac84-bd3a3246023e",
"email_verified": false,
"preferred_username": "user",
"given_name": "test",
"family_name": "user"
}
As seen, it doesnt give the roles at all. How do I then tell what roles this access token has? Interestingly, when I search for this, many resources are suggesting the above userinfo endpoint. But this merely tells me taht the access token I provided is valid. Does not give roles for that.
In other words - it authenticates but does not authorize.
Please suggest.
Thanks,
Anand
In Keycloak admin Console, you can configure Mappers under your client. Add a builtin Mapper of type "User Realm Role", then open its configuration e.g. change Token Claim Name if you want.
Client roles can be configured similarly, but they are returned by default in the token under the name resource_access.${client_id}.roles
The the client side you can parse the token to find the roles. E.g. In an angular application and using the keycloak-angular adapter, you can have a the token as a json object by calling keycloak.getKeycloakInstance().tokenParsed.
In a spring boot application and using the Keycloak java api, you can find the roles under the field "otherClaim" in the following class
https://www.keycloak.org/docs-api/10.0/javadocs/org/keycloak/representations/AccessTokenResponse.html
In both representations you will find the roles under the "Token Claim Name" defined in the client mapper configuration
Additionally, if the full scope is not allowed then you need to add the relevant roles to the scope, so they can appear in the token.
After adding role in the roles section , need to move available roles into the Assigned Roles of the scope tab of the respective client section.

Zoho API v2 login issue

We use the Zoho OAuth API's response to authenticate users in our app (RoloCRM). Our approach works for most of the accounts but is failing for a few users.
We have listed the steps below, with the APIs used in our app during login.
Step1: We use v2 of the Zoho OAuth API for login and get basic details.
https://www.zohoapis.com/oauth/v2/auth?scope=ZohoCRM.users.ALL,ZohoCRM.org.ALL,ZohoCRM.modules.ALL,ZohoCRM.settings.ALL&client_id=&&response_type=code&access_type=offline&redirect_uri=
Step2: Once we get the access & refresh token, we call below api to get currently signed in user's email and zoho-user-id.
https://www.zohoapis.com/crm/v2/users?type=CurrentUser
Step3: We call below api to get currently logged in user's organization id.
https://www.zohoapis.com/crm/v2/org
In step2, we receive currently logged in user's zoho-user-id. We expect this to be same across different zoho teams.
Is this assumption valid?
Example:
In one of our example, same user has 2 registered zoho organizations with 2 different email ids(Email1 and Email2).
User validated email1 with zoho, in step2 we get "zohouserid1" and
in step3 we get "zohoorgid1"
User validated email2 with zoho, in
step2 we get "zohouserid1" and in step3 we get "zohoorgid1"
We are getting same zohouserid and organization id for two different emails (belongs to same user).
Is it possible to get actual organization id and user id based on the logged in user's email?
It's a possibility you are not using the correct client_id for respective email-ids,make sure that when you use client_id for part(a) you must use the same client_id (for the give email-id you are using) in part(b) also.
(a) For dwest898#test.com : The client_id for this email-id in both code's should be same
echo "<a href='https://accounts.zoho.com/oauth/v2/auth?scope=ZohoSign.account.CREATE,ZohoSign.account.READ,ZohoSign.account.UPDATE,ZohoSign.documents.all,ZohoCRM.modules.ALL,WorkDrive.team.ALL,WorkDrive.workspace.ALL,WorkDrive.files.ALL&client_id=1000.NZAGLITT9FLS31433JQ23&response_type=code&access_type=offline&redirect_uri=http://localhost/zoho_leads/testaccesstoken.php'>Link</a>";
(b) For dwest898#test.com
$client_id = "1000.NZAGLITT9FLS31433JQ23";
$client_secret = "a94365a4a0ad7f64b039709b916b73a";
(a) For adev4314#test.com : The client_id for this email-id in both code's should be same
echo "<a href='https://accounts.zoho.com/oauth/v2/auth?scope=ZohoCRM.modules.ALL,WorkDrive.team.ALL,WorkDrive.workspace.ALL,WorkDrive.files.ALL&client_id=1000.RORGERNX224MJSQHA5QF7Q&response_type=code&access_type=offline&redirect_uri=http://localhost/zoho_leads/testaccesstoken.php'>Link</a>";
(b) For adev4314#test.com
$client_id = "1000.RORGERNX224MJSQHA5QF7Q";
$client_secret = "8eaa1d5c89b588567490fc95f33ca15";

How to access basic user information for "Private Users" on Instagram API?

I am writing an application and need to read basic Instagram user info such as username, #posts, #followers and etc. This works well for public users but for private users returns:
{
"meta":
{
"code":400,
"error_message":"you cannot view this resource",
"error_type":"APINotAllowedError"
}
}
Let's say I am signed in as user A, and we want to show information from User B which is private to user A (user B also authorized my application to access it's basic info). I am using the following end point to read user B information:
https://api.instagram.com/v1/users/<userB_ID>/?access_token=<myAccessToken>
Am I missing something? or should I use different end point?
Update (Solution #1)
It seems one solution to fix this is to use Query end point. I was trying to manage all my work with Instagram user IDs (not usernames) but it seems I have to use usernames for the query. Is there a way to use query with user ID?
Here is what it looks like:
https://api.instagram.com/v1/users/search?q=<UserB_Username>&client_id=<myClientID>
if <myAccessToken> is to get user A's info, you can't get User B's info with it. If you have a backend to this app, then you can store different access tokens for each user, and make the call with the appropriate access token, and feed the info to the app through your own API.

Rails 3 Linkedin API gem

I'm trying to set up the linkedin api in a rails 3 app using the linkedin gem. I don't want the user to have to authenticate my app in order for the API to get their info. I only need one piece of their public profile (the headline). So, maybe I should just be using xml or json to pull this off (not exactly sure how to get that with linkedin either).
I have the following in a helper so that I can call linkedin_header() in a loop of users. I only have 'client' as the last line of the following code while debugging. It outputs as expected (#). It seems like I am only a step away from success. How can I access a given users headline? I have tried using "client = client.profile(:url => 'linkedin_user_url')", but that return "Call must be made on behalf of a member".
def linkedin_header(account_user)
user = User.find(account_user)
account = Account.where(:user_id => user, :external_id => 1)
api_key = 'aaaaaaaa'
api_secret = 'bbbbbbbb'
client = LinkedIn::Client.new(api_key, api_secret)
rtoken = client.request_token.token # this returns correctly
rsecret = client.request_token.secret # this returns correctly
client
# client = client.profile(:url => 'linkedin_user_url')
end
So, I guess I have two questions. Is my request (public headline of any user) too simple for the above...should I be using XML or JSON. And, if Im close...can I make the API work for me without the user having to authenticate via linkedin.
Based off of what I read from the LinkedIn API reference (http://developer.linkedin.com/documents/authentication)
You have to make requests to their API only after being authenticated. (Using OAuth Keys) Rather than just grabbing the publicly available information.
It seems like since you want a small piece of information (the public headline of any user) you'd want some sort of implementation like Facebook's OpenGraph. After looking around on LinkedIn, I don't see any sort of public implementation like that.
I would suggest checking out this gem:
https://github.com/yatishmehta27/linkedin-scraper
It seems to be the type of solution you're looking for.

Resources