Not enough permissions to access: POST /dmpSegments - linkedin

I tried - POST https://api.linkedin.com/v2/dmpSegments
but got error -
{"serviceErrorCode":100,"message":"Not enough permissions to access:
POST /dmpSegments","status":403}
My app does have permission of rw_ads. I can successfully call some ads api endpoints, e.g.
- POST https://api.linkedin.com/v2/adSegmentsV2
- POST https://api.linkedin.com/v2/adCampaignGroupsV2
- POST https://api.linkedin.com/v2/adCampaignsV2
- POST https://api.linkedin.com/v2/adCreativesV2
public string CreateDmpSegment(string token, DmpSegmentsCreateRequest dmpSegmentsCreateRequest, ILogMessages messages)
{
NameValueCollection data = System.Web.HttpUtility.ParseQueryString("");
string url = $#"{LinkedInApiUrl}dmpSegments";
Tuple<NameValueCollection, dynamic> results = RestHelper.JsonApiPOST(url, token, dmpSegmentsCreateRequest);
if (string.Equals(results.Item1["valid"], true.ToString(), StringComparison.InvariantCultureIgnoreCase))
{
return results.Item2["X-LinkedIn-Id"];
}
UpdateErrors(LinkedInErrors.CreateDmpSegmentError, results, messages);
return null;
}
expected return results.Item2["X-LinkedIn-Id"];
but got error -
{"serviceErrorCode":100,"message":"Not enough permissions to access: POST /dmpSegments","status":403}

From what I read here you must have the access token generated with rw_dmp_segments scope. The rw_ads scope is not enough.
To be able to request access tokens with rw_dmp_segments scope, you have to obtain a further permission from LinkedIn as written here:
"..you must initiate a Technical Sign Off request by contacting your LinkedIn POC on the Business Development team."
Hope this helps.

Related

Firebase Realtime Database returns 401 when trying to authenticate?

I am using REST API in my app to communicate with a Firebase RTDB, and trying to use a Google Access Token to authenticate my requests.
My issue is that with even the most permissive Rules on the database, I get HTTP error 401 in response to queries that try to authenticate.
For example, say I try to put some data in my database with the following command, I get 401 in return (all the values within < > are placeholders):
curl -XPUT -d '{ "UserID" : "<GOOGLE_UID>", "UserName" : "Clicksurfer", "CompletionMoves" : 8, "CompletionTime" : 16.21979 }' https://<FIREBASE_URL>.firebaseio.com/Level2/<GOOGLE_UID>.json/?access_token=<GOOGLE_ACCESS_TOKEN>
401
The strangest part is, when I abandon the use of access token altogether the query works:
curl -XPUT -d '{ "UserID" : "<GOOGLE_UID>", "UserName" : "Clicksurfer", "CompletionMoves" : 8, "CompletionTime" : 16.21979 }' https://<FIREBASE_URL>.firebaseio.com/Level2/<GOOGLE_UID>.json
200
As I said, I am currently using the most permissive rules for debugging:
{
"rules": {
".read": true,
".write": true
}
}
Any idea what might be causing this? Thanks in advance
EDIT:
I use the Google Play Games plugin for Unity in my project, among other things to get the AuthCode.
In order to do this, I needed to do a couple of things:
When building the config for Google Play Games during startup, I made sure to call the RequestServerAuthCode(false) method
Have the user login after Google Play Games sets up
Make sure that the relevant ClientID was supplied to Unity (in this case, it is a web client that has auth permissions on my Firebase rtdb).
This all looks like this:
public class GPGSAuthentication : MonoBehaviour
{
public static PlayGamesPlatform platform;
void Start()
{
if (platform == null)
{
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().RequestServerAuthCode(false).Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.DebugLogEnabled = true;
platform = PlayGamesPlatform.Activate();
}
Social.Active.localUser.Authenticate(success =>
{
if (success)
{
Debug.Log("GSPS - Logged in successfully");
}
else
{
Debug.Log("GSPS - Falied to login");
}
});
}
}
Now that we've done this, we can call PlayGamesPlatform.Instance.GetServerAuthCode() in order to get the AuthCode.
I traded in my AuthCode for an Access Token by sending a POST request to https://www.googleapis.com/oauth2/v4/token. In my query, I supply 4 fields:
client_id, which has the ID of the previously used client (where we got the AuthCode from).
client_secret, which has the correlating secret.
grant_type, which is always with the value "authorization_code"
code, which has the value of the AuthCode we got.
In response, I get a 200 response with 4 parameters:
access_token, the token I (fail to) use when authenticating against my Firebase rtdb.
token_type, the type of the aforementioned token.
expires_in, the amount of time before the token expires (I presume in seconds unit)
refresh_token, a token which can be used in order to get a new access_token without having to keep the Google user connected.
I then supply this access_token value to the queries I send to my DB, and promptly get the 401 error.

Issue with jwt-bearer on-behalf-of grant in Azure AD

So I have an Angular app that uses the adal-angular library to authenticate with an ASP.NET Core 2.0 Web API. The API then uses on-behalf-of flow to authenticate with another API using the users token like this MS article https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-on-behalf-of.
The issue I have is this is working fine in the DEV environment but I have now deployed a TST environment with separate App Registrations and I am receiving the following exception when I try and request the token using on-behalf-of
AADSTS240002: Input id_token cannot be used as 'urn:ietf:params:oauth:grant-type:jwt-bearer' grant.
The code I am using to request the token
public async Task<string> AcquireTokenAsync(string resource)
{
try
{
string accessToken = await _httpContextAccessor.HttpContext.GetTokenAsync(AuthenticationConstants.AccessToken);
var credentials = new ClientCredential(_azureOptions.ClientId, _azureOptions.ClientSecret);
var authContext = new AuthenticationContext($"{_azureOptions.Instance}{_azureOptions.TenantId}")
{
ExtendedLifeTimeEnabled = true
};
// On-behalf-of auth token request call
var authResult = await authContext.AcquireTokenAsync(
resource,
credentials,
new UserAssertion(accessToken));
return authResult.AccessToken;
}
catch (AdalServiceException asex)
{
_logger.LogError(asex, $"Instance: {_azureOptions.Instance} Tenant: {_azureOptions.TenantId} ClientId: {_azureOptions.ClientId}");
throw;
}
catch (System.Exception ex)
{
_logger.LogError(ex, ex.Message);
throw;
}
}
And I have used Fiddler and it looks like all the correct parameters are being passed.
Any help would be very much appreciated. I have set knownClientApplications on the second API and I have granted permissions on the Angular backend API to the second API.
For me, I got it to work by changing BOTH of the following to true:
oauth2AllowImplicitFlow
oauth2AllowIdTokenImplicitFlow
See here for more information.
According to your question and the error, it should be caused by that you angular app is not a Native(public) app.
For using this OBO flow with this Grant type, your client must be a public client not credential client.
If you want to register your client as a WebApp/API, you can refer to this Implementation:
Hope this helps!
Update
According to OP's comment, he/she got it working by changing oauth2AllowImplicitFlow from false to true.
We had this problem last week with one Azure Service Registration and not another. A review found that the token didn't return an AIO being returned. It turns out that the registration had redirects with wildcards (e.g., https://*.ngrok.io) and this is incompatible with the AcquireTokenOnBehalfOf function. I'm posting this here so a future person, probably me, will find it.
I was having problems even when oauth2AllowImplicitFlow and oauth2AllowIdTokenImplicitFlow were set to true. One of my Reply URLs had a wildcard in it. When the wildcard was removed, the issue was resolved.

Token based authentication http interceptor

I would like your opinion in order to achieve something. I have an api and I want to restrictionate the access of the user. But short story long, in action login controller of page /login I generate the token for the user autheticated and I return it. Well, here comes one of my question/problem. It's mandatory in a action controller to return a response, and my token it's send in json format and it's displayed on browser, but I don't want this, I just want to keep in response or in something so that my angular part to take that token and to take care of it in its way. So my method login:
public function loginAction(Request $request)
{
$username= $this->get('security.token_storage')->getToken()->getUser()->getEmail();
$serviceUser = $this->container->get('ubb_user_login');
$tokenUser = $serviceUser->generateToken($username);
$response = new JsonResponse(array('Token' => $tokenUser));
return $response;
}
2nd problem. I do not know in angular where to extract the token. In a controller I tried something:
app.controller('loginApi', function ($scope, $http, $window){
$http.get(
'/api/user/login'
).then(function (success) {
$scope.token = success.data.Token;
$window.localStorage.setItem('Token', token); // it's okay used like this localStorage?
});
});
Here, I want only to take the token from /login action, to save it in local storage, and then to display it on every request using $http request interceptor. That part works. If I send a random string in header auth it's working and it gives me access to api:
function httpInterceptor() {
return {
request: function(config) {
config.headers.authorization = 'jdjdnnkdkd';
return config;
},
responseError: function(errorResponse) {
switch (errorResponse.status) {
case 403:
window.location = '/login';
break;
case 401:
window.location = '/login';
}
return $q.reject(errorResponse);
}
}
}
So, the problems I encounter:
1) How to send the token in order for angular to take it, but to not be displayed in the browser? Let's say that I have a menu that access the api, and if the user it's not authenticated,clicking on a link unauthenticated it's sending me on the login page, and after I auth with success, to redirect me on the menu?
2) After returning the token, where exactly to use it in angular? In which controller? And how to save it?
Much appreciation, thank you.
It seems like you need a separate api resource for working with the tokens. Have you tried using FOSOAuthServeBundle? It helps a lot with setting up oauth authentication, tokens etc.
In general you need to have a separate call for the token, i.e.:
angluar app makes request to a get token resource, a token is returned and temporarily stored in the angular app
use that token for each subsequent request - check the oauth bundle config on how to set which urls have to be oauth protected, but that bundle takes care of this for you
Regarding your angular issue, look at this q/a How to store authentication bearer token in browser cookie using AngularJS

Service account authentication

I'm trying to create calendar event via PHP for one particular user - say developement#example.com.
I've created Service Account in Google Developers Console, got ClientID, E-mail address and private key. The authentication is done with code:
$client = new Google_Client();
if (isset($_SESSION['service_token'])) {
$client->setAccessToken($_SESSION['service_token']);
}
$cred = new Google_Auth_AssertionCredentials(
'somelongstring#developer.gserviceaccount.com.',
array('https://www.googleapis.com/auth/calendar','https://www.googleapis.com/auth/calendar.readonly'),
file_get_contents('p12 file'));
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$_SESSION['service_token'] = $client->getAccessToken();
This type of authentication seems pretty OK. But all events are created as user with E-mail address somelongstring#developer.gserviceaccount.com instead of developement#example.com.
I've tried setting sub parameter:
$cred = new Google_Auth_AssertionCredentials(
....
$cred->sub = 'developement#example.com';
$client->setAssertionCredentials($cred);
But this piece of code throws exception:
Google_Auth_Exception: Error refreshing the OAuth2 token, message: '{ "error" : "access_denied", "error_description" : "Requested client not authorized." }'
And now I'm lost. Any advice?
OK, resolved ;-)
Problem was with developement on own domain.
As mentioned in other question and in Google SDK Guide I have to grant access for service account to all scopes I request access. I forgot to add read-only scope.

Extending Access Token Expiration not functioning

I am at the intermediate level in php and am new with facebook development. I have looked through the facebook documents and Stack Overflow previous comments.
All I basically wanted to do was let the user log in with their Facebook account and display their name.
My php page has a graph, and the page auto refreshes every 2 or 5 min.
I authenticate and get the facebook first_name to put on the page.
$graph = $facebook->api('/me');
echo $graph['first_name'] to get the first name of the user .. (for which I thought that no access token was required).
After about 90 min. I have been receiving the error:
fatal error: Uncaught OAuthException: An active access token must be used to query information about the current user......
and I have no value ( 0 ), in the $facebook->getUser(); parameter
I do know that off line access permission has been depreciated, (and I have have this enabled in my apps advanced settings)
I am trying to get an extended access token. In the FB docs. I see:
https://graph.facebook.com/oauth/access_token?
client_id=APP_ID&
client_secret=APP_SECRET&
grant_type=fb_exchange_token&
fb_exchange_token=EXISTING_ACCESS_TOKEN
I included my information in the link(an existing valid access token and all) and received a access token:
access_token=AAADbZBPuUyWwBAFubPaK9E6CnNsPfNYBjQ9OZC63ZBN2Ml9TCu9BYz89frzUF2EnLttuZAcG2fWZAHbWozrvop9bQjQclxVYle7igvoZCYUAg2KNQLMgNP&expires=4050
Yet this token expired in about 1 hour or so.(....expires=4050)
I assume I am using server side auth because I am using PHP?
I assume you need to enable "deprecate offline_access" in your Apps Advanced Settings page. As this worked for me:
//added code in base_facebook.php inside the facebook class
public function getExtendedAccessToken(){
try {
// need to circumvent json_decode by calling _oauthRequest
// directly, since response isn't JSON format.
$access_token_response =
$this->_oauthRequest(
$this->getUrl('graph', '/oauth/access_token'),
$params = array( 'client_id' => $this->getAppId(),
'client_secret' => $this->getAppSecret(),
'grant_type'=>'fb_exchange_token',
'fb_exchange_token'=>$this->getAccessToken(),
));
} catch (FacebookApiException $e) {
// most likely that user very recently revoked authorization.
// In any event, we don't have an access token, so say so.
return false;
}
if (empty($access_token_response)) {
return false;
}
$response_params = array();
parse_str($access_token_response, $response_params);
if (!isset($response_params['access_token'])) {
return false;
}
return $response_params['access_token'];
}
The token can still be invalid for several reasons, See How-To: Handle expired access tokens.
Hope it helps
There's a bug on this:
https://developers.facebook.com/bugs/241373692605971
But, another question on SO has a workaround (user uninstalls and re-installs):
fb_exchange_token for PHP only working once user removes app

Resources