Discover owner of Twitter app via consumer_key and consumer_secret - twitter

I have inherited a legacy web application that contains API credentials for a Twitter application.
I have the consumer_key and the consumer_secret.
How do I determine the actual account owner of the application?
Is there a way to regenerate the API credentials without knowing the actual account information (i.e. username/password)?

Perhaps you can get some additional information if you have an Access Token for the app, even if it has expired.
When you create a new app in https://apps.twitter.com you get:
Consumer Key (API Key)
Consumer Secret (API Secret)
If you want to use it, you have to create a Access Token, and the results will be two values:
Access Token
Access Token Secret
The page for the app under https://apps.twitter.com will show you the fields "Owner" and "Owner ID" for the app.
If you have an Access Token value --you should have one if you are using the app--, you'll find something like:
'access_token' => '12345678-XxxXXxxXxxXxX1XXXXxx2xXXxXxXXX3xXXxxxxxXX'
The value at the beginning of that value, just before the hyphen (that is, 12345678 in that example) will be the Owner ID of the user that created the Access Token (you'll have to use your actual value, instead of the 12345678 of the example).
If you go to
https://tweeterid.com/
and enter the Owner ID extracted from Access Token field (that will be the same of the app, for example: 20749410), you'll obtain the Owner (#finkd = Mark Zuckerberg in this case).
If you are lucky, and the user that create the Access Token is the same that created the app, you'll have the answer to your question. It they aren't the same person, at least you can get a minor clue to follow investigating.

Email api#twitter.com. They should be able to reach out to the original developer.

Related

Google oauth2Client.getToken is not returning id_token for other users

I'm implementing Google's 'code model' of Oauth2 and having trouble getting users' email - I wonder if this is a scopes problem or my misunderstanding about how to set up the code model. This sequence of events is already working:
Client loads https://accounts.google.com/gsi/client
Client starts call to google.accounts.oauth2.initCodeClient
Client gets code
Client passes code to one of my server endpoints
Server has an oauth2Client set up using the config with client_id, client_secret, and redirect URL = 'postmessage'
Server exchanges the code from the client for tokens
Server does oauth2Client.setCredentials(tokens) - this contains an access_token, which is enough for the client to make API calls to, e.g., retrieve the user's Google Calendar
Server is able to do oauth2Client.getTokenInfo(tokens.access_token);
There are various places along the way that involve scopes; I am probably getting something confused here. The client's initial call (step 2 above) uses
scope: 'https://www.googleapis.com/auth/calendar',
My code path on the server does define scopes anywhere.
In GCP, my project is set up with scopes
calendar.calendarlist.readonly, calendar.readonly and calendar.events.readonly
openid
/auth/userinfo.email
Here's the problem I'm encountering: when I go through this flow as a user and oauth with the account that owns the GCP project (this is a Google Workspace email, in case that matters), the tokens object that the server receives (step 6 above) has access_token, refresh_token and id_token - the id_token can be decoded to yield the user's email, and the user's email is also in the response to oauth2Client.getTokenInfo(token.access_token).
However, when I go through the flow with my other (personal) Gmail account, the tokens object that the server receives is missing the id_token but has the access and refresh tokens. Question 1: why are the responses different?
Question 2: How can I get the email of the user on the server in the personal Gmail account case? I've tried having the server make a call to https://www.googleapis.com/oauth2/v2/userinfo?fields=id,email,name,picture with the access_token, but this fails. I am not sure if I'm supposed to declare scopes for oauth2Client somehow, or tap a Google API using a different method on the server.
I think I've had a breakthrough: in step 2 in my original post, when I did "Client starts call to google.accounts.oauth2.initCodeClient", I had set the scope of initCodeClient to just the calendar scope. When I changed it instead to scope: 'https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/userinfo.email openid', (scope takes a space-delimited list in this case), it allowed my server call to get the id_token for this user and oauth2Client.getTokenInfo to get a response with the user's email in it.
When I updated the scopes like that, the popup asking for authorization also updated to request all the scopes I wanted - previously, it was only asking for the Calendar scope, so it makes sense Google didn't want to return the email.
What I still don't understand is why my previous setup was working for the account that owns the GCP project. In other words, when I was first building it out with that owner account, the client was only noting the Calendar scope while the server was asking for all three scopes (ie there was a mismatch), and the server was still able to get an id_token and the user's email in getTokenInfo. Maybe the owner account has some special privilege?

Twinfield do you need sessions if using oAuth?

I’m updating a third party app that currently integrates with Twinfield using the session’s method with username and password to use the oAuth method.
In confused by the documentation though... do I still need to use the sessions or when using oAuth do I just call the endpoint(s) by passing the access token in the header as normal?
Also their Soap definition has four properties, the usual ClientID and Secret but also accessSecret? What’s that?
TLDR: you no longer need to use the sessions and SelectCompany; when you have the access token you can use that and the company code directly in the header.
You can obtain the access token as described here.
The documentation is a bit unclear on how to use the access token in your calls.
In the old username/password/session flow, you referred to a SessionID in the SOAP Header, and you would do a SelectCompany call to select the relevant target ("administratie").
In the OAuth flow, the SessionID is no longer relevant. Once you obtained a valid access token, you should set that in the header using the AccessToken field.
Instead of the old SelectCompany call, you can set the CompanyCode directly in the header. So if you have obtained an access token eyWhatANiceToken, and want to retrieve data for company "My Company BV [130001]" you have set AccessToken to eyWhatANiceToken and CompanyCode to 130001 in the header.
You can request the available codes using the list offices call

How does a JWT token with an empty payload work?

I'm working with the Snapchat API to try and log into an app using their OAuth flow. Once the user is logged in via Snapchat, I'm trying to reverse engineer (since they have no documentation on this) how to obtain some sort of unique ID for the user so I can associate them with a local user in my database. This is how I have previously done this with things like Facebook. The user logs in and gets an access token via the Facebook Api, and I can extract some kind of unique ID for the user via the Facebook API.
The Snapchat API only allows you to access the user's display name and some "externalId", which I cannot guarantee won't change. So I decoded the JWT token that Snapchat issued to me and it challenged my understanding of how JWT tokens work. When I decoded the token at http://jwt.io, I saw that the payload was empty, yet the token works when calling the https://kit.snapchat.com/v1/me endpoint. How is the snapchat server able to identify who I am? I've always had the understanding that the JWT must include a claim such as sub which identifies the user. The server can then use that information to know who I am.
In this case, my JWT payload is empty, but the aforementioned endpoint still returns my user data. What is happening here? How does the server know who I am when my JWT token has an empty payload? To me they must be storing a copy of my JWT token on the server, which seems like the incorrect way to use JWT tokens. Perhaps my understanding is terribly wrong. Any thoughts?
The payload of a JWS (signed token) can be detached and transmited to the audience by other means.
This feature is described in the Appendix F of the specification.
With the JWS compact serialization mode (the most common format), a token looks like THE_HEADER.THE_PAYLOAD.THE_SIGNATURE. With a detached payload it is identical except that THE_PAYLOAD is an empty string: THE_HEADER..THE_SIGNATURE.
The verification of the signature is the same as with an attached payload. The receiver should have received the payload and must recreate the full input i.e. THE_HEADER.THE_PAYLOAD.
Regarding the identification performed by snapshat, a reference to the detached payload may be set in a header parameter of the token (first part of the token) allowing Snapchat to fully verify the token.

Restricting api access by client

I have an identity server built with Identity server 4. There is one main API with several angular web applications build by third party customers that access this API endpoint.
Now I would like to create a second API but its only for internal use with OUR official plugin. I am trying to figure out how to lock it down so that only our app can access it. I am not a fan security by obscurity and assuming that the third party's dont know its there so wont try and access it.
My first thought was to add a new scope for this API but by doing that its going to popup and ask the users for access to the data which isnt really need.
The only thing i can think of would be to check the client id some how in the API and add a policy for it. This really isnt right ether as to my understanding polciy should be checking stats of the user and not the client itself.
services.AddAuthorization(
options => {
options.AddPolicy("DevConsole", policy => IsClientId(xxxx)
}
);
Is it possible to lock down an API based upon a single client id? or am i going at this in the wrong way.
Another idea i had was to add another claim if they login with this client id which seams like overkill to me.
Example:
Lets say that I have an API endpoint that allows you to update the usersname. All users have access to their name this isnt a scope issue. However only our official app has access to update the usersname. Any app created by third party developers do not have access to the endpoint to update a usersname.
So our official plugin has a client id of 123 and yours has a client id of 321. A user logged though client id 321 can not access this endpoint. User logged in though client id 123 can.
I am starting to think this isnt possible because Oauth and Openid are completely user based. There is no way to validate the user based upon the client they authenticated with.
if I understand the problem correctly, I would create a new Client on Identity Server, for the "main API" and a new Resource for the "internal API"
This would allow the "main API" to also be a client, with client credentials grant type, therefore it has a id+secret and is allowed to request a token for itself. In this case, you will now request the newly created scope for in "internal API" and the users will have no knowledge that this entity evens exists.
After going back and forth with this with this it occurred to me that the client id is returned as a claim. So when i got in this morning i checked.
This should enable me to add a policy for only our official plugin.
services.AddAuthorization(options =>
{
options.AddPolicy("IsOfficalApp", policy => IsCheckOfficalClient());
});
This should enable me to lock down the API endpoints in question without requiring additional authorization from the users.

How to make API requests with an access_token for a Service Account

My end goal is to be able to retrieve place details from Google's API.
I need to do this as a Service Account, since this is kicked off as a background task on my server. Service Accounts require you to exchange a JWT (JSON Web Token) for an access_token. I finally got that working and am receiving an access_token. Phew.
Now however, I don't know what to do with this access_token.
The Place Details API says that the key parameter is required, but I don't have a key. Just an access_token. Using that value for key or changing the name of the paramater to access_token is not working.
Ultimately I need to be able to hit a URL like so:
https://maps.googleapis.com/maps/api/place/details/json?reference={MY_REFERENCE}&sensor=false&key={MY_ACCESS_TOKEN}
How do I use my Access Token to make a request to the Google Place Detail APIs?
Update 1
Still no success, but I thought I'd post the details of my request in case there's something wrong with what I'm submitting to Google.
I'm using the JWT Ruby library, and here are the values of my claim set:
{
:iss => "54821520045-c8k5dhrjmiotbi9ni0salgf0f4iq5669#developer.gserviceaccount.com",
:scope => "https://www.googleapis.com/auth/places",
:aud => "https://accounts.google.com/o/oauth2/token",
:exp => (Time.now + 3600),
:iat => Time.now.to_i
}
Looks sane to me.
Create the service account and its credentials
You need to create a service account and its credentials. During this procedure you need to gather three items that will be used later for the Google Apps domain-wide delegation of authority and in your code to authorize with your service account. These three items are your service account:
• Client ID.
• Private key file.
• Email address.
In order to do this, you first need a working Google APIs Console project with the Google Calendar API enabled. Follow these steps:
Go to the Google APIs Console.
Open your existing project or create a new project.
Go to the Service section.
Enable the Calendar API (and potentially other APIs you need access to).
You can now create the service account and its credentials. Follow these steps:
Go to the API Access section.
Create a client ID by clicking Create an OAuth 2.0 client ID...
Enter a product name, specify an optional logo and click Next.
Select Service account when asked for your Application type and click Create client ID.
At this point you will be presented with a dialog allowing you to download the Private Key as a file (see image below). Make sure to download and keep that file securely, as there will be no way to download it again from the APIs Console.
After downloading the file and closing the dialog, you will be able to get the service account's email address and client ID.
You should now have gathered your service account's Private Key file, Client ID and email address. You are ready to delegate domain-wide authority to your service account.
Delegate domain-wide authority to your service account
The service account that you created now needs to be granted access to the Google Apps domain’s user data that you want to access. The following tasks have to be performed by an administrator of the Google Apps domain:
Go to your Google Apps domain’s control panel. The URL should look like: www.google.com/a/cpanel/mydomain.com
Go to Advanced tools... > Manage third party OAuth Client access.
In the Client name field enter the service account's Client ID.
In the One or More API Scopes field enter the list of scopes that your application should be granted access to (see image below). For example if you need domain-wide access to the Google Calendar API enter: www.googleapis.com/auth/calendar.readonly
Click the Authorize button.
Your service account now has domain-wide access to the Google Calendar API for all the users of your domain, and potentially the other APIs you’ve listed in the example above.
Below is a description that uses a service account to access calendar data in PHP
The general process for service account access to user calendars is a follows:
• Create the Google client
• Set the client application name
• If you already have an Access token then check to see if it is expired
• If the Access token is expired then set the JWT assertion credentials and get a new token
• Set the client id
• Create a new calendar service object based on the Google client
• Retrieve the calendar events
Note: You must save the Access token and only refresh it when it is about to expire otherwise you will receive an error that you have exceeded the limit for the number of access tokens in a time period for a user.
Explanation of Google PHP Client library functions used:
The client object has access to many parameters and methods all of the following are accessed through the client object:
Create a new client object:
$client = new Google_Client();
Set the client application name:
$client->setApplicationName(“My Calendar App”);
Set the client access token if you already have one saved:
$client->setAccessToken($myAccessToken);
Check to see if the Access token has expired, there is a 30 second buffer, so this will return true if the token is set to expire in 30 seconds or less. The lifetime of an Access token is one hour. The Access token is actually a JSON object which contains the time of creation, it’s lifetime in seconds, and the token itself. Therefore no call is made to Google as the token has all of the information locally to determine when it will expire.
$client->isAccessTokenExpired();
If the token has expired or you have never retrieved a token then you will need to set the assertion credentials in order to get an Access token:
$client->setAssertionCredentials(new Google_AssertionCredentials(SERVICE_ACCOUNT_NAME,array(CALENDAR_SCOPE), $key,'notasecret','http://oauth.net/grant_type/jwt/1.0/bearer',$email_add));
Where:
SERVICE_ACCOUNT_NAME is the the service account email address setup earlier.
For example:’abcd1234567890#developer.gserviceaccount.com’
CALENDAR_SCOPE is the scope setup in the Google admin interface.
For example: ‘https://www.googleapis.com/auth/calendar.readonly’
$key is the content of the key file downloaded when you created the project in Google apps console.
$email_add is the Google email address of the user for whom you want to retrieve calendar data.
Set the client id:
$client-setClientId(SERVICE_CLIENT_ID);
Where:
SERVICE_CLIENT_ID is the service account client ID setup earlier.
For example: ‘abcd123456780.apps.googleusercontent.com’
Create a new calendar service object:
$cal = new Google_CalendarService($client);
Several options can be set for calendar retrieval I set a few of them in the code below, they are defined in the api document.
$optEvents = array('timeMax' => $TimeMax, 'timeMin' => $TimeMin, 'orderBy' => 'startTime', 'singleEvents' => 'True');
Get the list of calendar events and pass the above options to the call:
$calEvents = $cal->events->listEvents('primary', $optEvents);
Loop through the returned event list, the list is paged so we need to fetch pages until the list is exhausted:
foreach ($calEvents->getItems() as $event) {
// get event data
$Summary = $event->getSummary();
$description = $event->getDescription();
$pageToken = $calEvents->getNextPageToken();
if ($pageToken) { // if we got a token the fetch the next page of events.
$optParams = array('pageToken' => $pageToken);
$calEvents = $cal->events->listEvents('primary', $optParams);
} else {
break;
}
}
Get the Access token:
$myAccessToken=$client->getAccessToken();
Save the access token to your permanent store for the next time.
The language isn't important php, ruby, .net, java the process is the same. The api's console shows the Places API as supporting service accounts so it should be possible to access it.
As far as using the token please have a look at https://code.google.com/p/google-api-ruby-client/ code as the usage is clearly defined in the code repository. Doesn't make any difference if the access token is for a service account or a single user the process for using the token is the same. See the section titled "Calling a Google API" in the following link: https://developers.google.com/accounts/docs/OAuth2InstalledApp
The access token is sent in the http authorization header along with the request.For a calendar request it would look something like the following:
GET /calendar/v3/calendars/primary HTTP/1.1
Host: www.googleapis.com
Content-length: 0
Authorization: OAuth ya29.AHES6ZTY56eJ0LLHz3U7wc-AgoKz0CXg6OSU7wQA

Resources