I got issue to post on users profile (Not got error on all users).
Error Code: 400
Error Message: Calls to this method must be made by or on behalf of a Google+ Page.
$options = array( "headers" => array( 'content-type' => 'application/json;' ), "body" => json_encode($activity) );
$httpClient = $this->gplus->client->authorize();
$request = $httpClient->post("googleapis.com/plusPages/v2/people/$Id/activities";, $options);
$response = $request->getBody();
$googlePostResponse = $response->getContents();
$googlePostResponse = json_decode($googlePostResponse, TRUE);
The code you are currently using is to the Google Domains api. The error means that the user you have currently authenticated with doesnt have access to the domains account. Make sure to grant the user access and they will be able to post to the Domains google+ page authentication
Note:
There is a difference between the Google+ API (Socialmedia website) and the Google Domains API (Gsuite)
The google+ api is read only and does not allow for programiticly inserting posts into Google+.
How authentication works
When you authenticate your application using these scopes
$this->client->addScope('googleapis.com/auth/plus.me');
$this->client->addScope('googleapis.com/auth/plus.stream.write');
$this->client->addScope('googleapis.com/auth/plus.stream.read');
$this->client->addScope('googleapis.com/auth/plus.pages.manage');
$this->client->addScope('googleapis.com/auth/plus.media.readwrite');
You are asking the user can I do these things on your behalf. However if the user does not have permission to do something your not going to be able to do it.
calls to this method must be made by or on behalf of a Google+ Page.
The user you are authenticating with does not have access to a business page. So your application cant write to a business page. You can only post to a domain account if you have a gsuite account. If you don't have one then you cant post to it. you cant just give them the id of your business page because again they dont have access to write to your business page.
Related
Bit of an odd one. I have an endpoint to log the user into Google and grant the Google Drive authentication scope for access to a user's drive account. This is said function
if(Auth::check() && $profile->abilities()->contains('manage_docs') && $request->input('redirect_uri') && $request->input('community')) {
$scopes = [
'https://www.googleapis.com/auth/drive',
];
return Socialite::driver('google')->scopes($scopes)->with([
'state' => "sso.redirect.uri=" . $request->input('redirect_uri'). "&type=documents",
"access_type" => "offline",
"prompt" => "consent select_account"
])->redirect();
}
When a user hits this endpoint, they get redirected to Google. Users are reporting they see that they are being asked to grant access to Google Drive from my application, however their credentials do not have the above listed scopes. However, if they remove the Google Account and resign in (using the same method), they get the required scopes..
Tldr, first pass through this method doesn't add the scope, 2nd time through grants correct scopes.
If in doubt, doubt the user's ability to press the tick box to grant the auth scope...
I'm currently making an API for a mobile app but I think I'm a bit confused with how email verification and authentication is meant to work. I'm attempting to implement the following flow:
User registers in the mobile app and it sends a request to the API
Laravel creates the user and fires off an email
User receives the email and clicks on the link
Laravel verifies the user and redirects them to the mobile app via deep-link
However when the user clicks the email link a "route login not defined" error is rendered.
Which makes sense, because the user is not authenticated at the time. But am I getting this wrong?
Should I authenticate the user prior to sending the email? And will that work, given that we're using Sanctum rather than "regular" authentication?
Currently this is what I'm doing:
// web.php
Route::get('/email/verify/{id}/{hash}', [EmailVerificationController::class, 'verify'])
->middleware('signed') //note that I don't use the auth or auth:sanctum middlewares
->name('verification.verify');
// EmailVerificationController.php
public function verify(Request $request)
{
$user = User::findOrFail($request->id);
if ($user->email_verified_at) {
return '';
}
if ($user->markEmailAsVerified()) {
event(new Verified($user));
}
return redirect()->away('app://open'); // The deep link
}
Is there any security risk here? Should I at any point authenticate the user before or after they click the link?
I wanted to avoid rendering "web views" as much as possible.
I think that the best way is to implement two different paths based on the source of the user.
Regular email validation for users coming from a browser
The user will just follow the link delivered by email, you can do that with or without authentication (maybe with transparent cookie authentication). If the validation is fulfilled redirect them back to the home page.
Mobile users coming from the mobile application
I would send a PIN (with some kind of expire mechanism) via email and ask them to put it inside the APP to verify the account. This can even be protected with auth middleware using the JWT token with the verification API call.
I don't see any security issue with this last one.
Implementing Chargebee Portal Session integrating it into my app.
If the users subscription is inactive, Im redirecting them to the portal to update their subscription.
The API provides:
redirect_url
URL to redirect when the user logs out from the portal.
My (ruby) code is like this, matches the example in the API:
result = ChargeBee::PortalSession.create({
:customer => {
:redirect_url => current_lessons_url,
:id => chargebee_customer_token
}
})
I get the portal loading just fine.. but how does the user logout.. and trigger the return to my app? I can't see it.
Here's how it looks for me. How does the user logout and initate a return to my app?
Assuming that you are using SSO via API portal auth setup,
In order to handle the Logout scenario, you can call Chargebee's Logout a portal session API endpoint and pass the respective portal session ID from which the user is trying to log out. So on logout call, the redirect URL passed in the create function is used and the end-user is redirected to the specified URL destination/app.
Reference - https://apidocs.chargebee.com/docs/api/portal_sessions?lang=ruby#logout_a_portal_session
I have setup Passport in Laravel 5 and am creating a token when a user registers by using this..
$user->createToken('My Token')->accessToken;
When I create a new user then I can see an entry in the oauth_access_tokens table that looks like this, I have shortened the id for display...
id | user_id | client_id | name | scopes | revoked
-----------------------------------------------------------
765765 | 193 | 1 | My Token | [] | 0
The API route I want to allow access to is protected, now I am trying to allow access by passing the following headers in Postman...
Authorization | Bearer 765765
Accept | application/json
But this is returning a response of unauthenticated, where am I going wrong?
Laravel Passport uses oAuth2. It's not as simple as generating a user token and being able to use it to authenticate. oAuth2 requires another step, which is called a token exchange.
You will have seen the oAuth2 process in action when you log into a website with Facebook. You click the login with Facebook button and you are sent to Facebook and you are presented with a dialog where you're asked to confirm or deny an app access to your account (Usually, specific parts of your account, a.k.a scopes).
That website will have it's own client account with Facebook and will have its own client ID and client secret. When you click that button, the website sends you to Facebook in order to gain your permission and an authorization code from Facebook. The website passes its client ID, requested permissions (scopes), a randomly generated session state (So it can verify later) and a URL to redirect to Facebook where you are shown the dialog.
When you accept, Facebook generates what is called an authorization code and sends you back on your way to the website (The redirect URL specified) along with the sessions state (So the website is able to verify the request) and the authorization code.
The website, on its back end will then ask Facebook to exchange your authorization code for an access token and will provide its client ID and client secret so Facebook is able to verify its authenticity. Facebook then responds with an access token and an expiry time.
Now, the website is able to access your account using the access token to be able to grab the requested information (Such as your email address for login).
It's also possible to do skip a lot of this process and not require the user to have to follow the whole redirection flow. To do this, (In Passport at least), you will need a password grant client. This is usually what you would do if you are using oAuth2 to authenticate an API.
The process here would be to generate a password grant client:
php artisan passport:client --password
In your database, the you will find in the oauth_clients table, a password grant client with a client ID and secret. You would need to give this to whoever is consuming your API (Such as a mobile/cellphone app).
Now when your user wants to log in, the consumer of your API (In this case Postman) would need to provide the user's credentials (username/password) as well as the client ID and secret for your password grant client. It's also necessary to tell Passport that you want to authorize via password grant.
The example given in the docs looks like this:
$response = $http->post('http://your-app.com/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => 'client-id',
'client_secret' => 'client-secret',
'username' => 'taylor#laravel.com',
'password' => 'my-password',
'scope' => '',
],
]);
When successful, Passport will return a 200 response and will return some JSON containing an access token and a refresh token. You use the access token to access the user's account and you use the refresh token to get a new access token (without requiring the user to log in again).
It is this access token that you need to provide as the Bearer in your Authorization header.
I wrote a PHP application which tries to create an User in my Google Directory. I don't use the Google Libraries. I succeded making requests to the Android Enterprise API. I can enroll and unenroll Enterprise Service Accounts with my MSA. So I assume my Code for the JWT and Requests work.
I created a Service Account and enabled "Domain Wide Delegation" and added the following permission "https://www.googleapis.com/auth/admin.directory.user, https://www.googleapis.com/auth/admin.directory.group" to my API Client under the "Manage API client access" windows.
My Service Account has the status role "Editor" in the "Permissions for project" windows.
So first my script gets the Bearer token from the Google Server, for that I create a JWT and encrypt it with my private key.
The Token contains the following fields
"iss" => sacname#projectname.iam.gserviceaccount.com
"scope" => "https://www.googleapis.com/auth/admin.directory.user, https://www.googleapis.com/auth/admin.directory.group"
"aud" => "https://www.googleapis.com/oauth2/v4/token",
"exp" => timestamp+3000,
"iat" => timestamp
When I do that request I get a bearer token, but when I use that token to make the insert request I always get the message "Not Authorized to access this resource/api" with an HTTP 403.
When I add the field "sub" to my JWT and specify the email of the Project admin "admin#mydomain.com" I can't even get the bearer token, then I get a 401 error with the following message "Unauthorized client or scope in request."
After that I tried something "easy", I just wanted to get a list of all users in my directory. But the Google Server just reponds with an "bad request" error. I got the same error with the API Explorer which is on API Page. Maybe the API is broken ? At least the API Explorer should work.
https://developers.google.com/admin-sdk/directory/v1/reference/users/list
Do you have some ideas why I can't create users with my service account ?
(I had to insert some spaces in the scopes and urls because I'm not allowed to post more than two links)
Greetings
Philip
Adding the sub claim is the right thing to do, because you must impersonate a super admin to use Directory API. If you get a "Unauthorized client or scope in request" response, that might be because there's a typo in the service account client ID you used to authorize (or the scopes), or that not enough time has passed (it usually propagates within a few minutes, but could take up to 24 hours).
See JWT error codes for more details on possible errors and causes.
Do you have some ideas why I can't create users with my service account?
Yes. Your service account seems to have no authority to create users. Check your Service Account's role in GDC to check if it's Owner, Editor, Viewer,etc. The scope of what they can do depends on that. Watch this Google video for a live demo.
Also, try to read more on Using OAuth 2.0 for Server to Server Applications.