Using oauth2_access_token to get connections in linkedIn - api

I'm trying to get the connections in linkedIn using their API, but when I try to retrieve the connections I get a 401 unauthorized error.
in the official documentation says
You must use an access token to make an authenticated call on behalf
of a user
Make the API calls You can now use this access_token to make API calls on behalf of this user by appending
"oauth2_access_token=access_token" at the end of the API call that you
wish to make.
The API call that I'm trying to do is the following
Error -->
http://api.linkedin.com/v1/people/~/connections:(id,headline,first-name,last-name)?format=json&oauth2_access_token=access_token
I have tried to do it with the following endpoint without any problems.
OK --> https://api.linkedin.com/v1/people/~:(id,first-name,last-name,formatted-name,date-of-birth,industry,email-address,location,headline,picture-urls::(original))?format=json&oauth2_access_token=access_token
this list of endpoints for the connections API are described here
http://developer.linkedin.com/documents/connections-api
I just copied and pasted one endpoint from there, so the question is what's the problem with the endpoint for getting the connections? what am I missing?
EDIT:
for the preAuth Url I'm using
https://www.linkedin.com/uas/oauth2/authorization?response_type=code&client_id=ConsumerKey&scope=r_fullprofile%20r_emailaddress%20r_network&state&state=NewGuid&redirect_uri=Encoded_Url
https://www.linkedin.com/uas/oauth2/accessToken?grant_type=authorization_code&code=QueryString_Code&redirect_uri=EncodedCallback&client_id=ConsummerKey&client_secret=ConsumerSecret
please find attached the login screen requesting the permissions
EDIT2:
Switched to https and worked like a charm!

Access tokens are issued for a specific scope that describes the extent of the permission you are requesting. When you start the authentication transaction, you add a specific parameter (called scope) that requests the user to consent access to what you want (in this case their connections). If I remember correctly, in LinkedIn that is r_network.
Check their documentation here: http://developer.linkedin.com/documents/authentication#granting
So, your call is perfectly ok, but very likely your access_token doesn't have enough privileges.

apiHelper.getRequest(getActivity(),"https://api.linkedin.com/v1/people/~/connections?modified=new", new ApiListener() {
#Override
public void onApiSuccess(ApiResponse response) {
}
#Override
public void onApiError(LIApiError error) {
}
});
If you are trying to get user connections using the LinkedIn SDK for android like in the snippet above,
Check for permissions in the SDK in this class com.linkedin.platform.utils.Scope.
Make sure r_network is available when building your scope. Example
public static final LIPermission R_NETWORK = new LIPermission("r_network", "Your network");
Can now be used like this to build scope
Scope.build(Scope.R_BASICPROFILE, Scope.R_EMAILADDRESS, Scope.W_SHARE, Scope.R_FULLPROFILE, Scope.R_CONTACTINFO, Scope.R_NETWORK)

Related

Google OAuth2 fails to redirect back to site, instead takes me to Google's My Account Page

I am using Google's PHP API client within a Laravel application to authorize a user via OAuth2 for the Analytics read-only API. I've used similar code on a previous project without issues, but this time it takes me to either Google's My Account page, or YouTube's account page, depending on the account I try to authorize with.
I have verified it is receiving the correct redirect_uri.
Here's some relevant code:
$google = new \Google_Client();
$google->setAuthConfig(resource_path('../client_secrets.json'));
$google->setRedirectUri(url()->to('/google/authorize'));
$google->addScope(\Google_Service_Analytics::ANALYTICS_READONLY);
$google->setAccessType("offline");
$google->setApprovalPrompt('force');
// No code? Then we need to authorize with Google.
if (! $request->has('code')) {
$authUrl = $google->createAuthUrl();
return redirect()->to($authUrl);
}
FIXED.
Turns out Google was redirecting properly but for some reason the code wasn't recognizing it had the code query value attached properly. Split the redirect to a different method and got it working that way.

Getting all messages from Microsoft Teams

I'm trying to get all the messages from Microsoft Teams in my tenant, I have registered the application to Azure, set the correct permissions and grated admin privileges.
What I am getting confused about is creating a GraphServiceClient.
My app is more of an Daemon Application.
I would really appreciate if someone could give me an example of how to create the client correctly.
this is my code so far:
string[] graphScopes = { "https://graph.microsoft.com/.default" };
IConfidentialClientApplication app = ConfidentialClientApplicationBuilder
.Create("x")
.WithTenantId("x")
.WithClientSecret("x")
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(app);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
try
{
var messages = await graphClient.Teams["x"].Channels["x#thread.skype"].Messages.Request().GetAsync();
Console.ReadLine();
foreach(var item in messages)
{
Console.WriteLine(item.Body);
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
Console.Read();
}
I'm getting the following error no matter what I'm trying to get
Code: UnknownError Inner error: AdditionalData: request-id: x date: 2020-05-27T14:22:37 ClientRequestId:x
update: I was able to get something from the API, I had wrong permissions.
still can't get the messages though,
I have all these permission:
ChannelMessage.Read.All, Group.Read.All, Group.ReadWrite.All
I'm probably missing the "ChannelMessage.Read.Group (RSC)" permission but I can't find it in the permissions page.
May this is the solution or the problem ;-)
Microsoft Teams APIs in Microsoft Graph that access sensitive data are considered protected APIs. These APIs require that you have additional validation, beyond permissions and consent, before you can use them.
https://learn.microsoft.com/en-us/graph/teams-protected-apis
Your problem is you are accessing a "beta" api but using the production base url path.
The permission you need is ANY of the following (i.e. or not and):
ChannelMessage.Read.Group (RSC) OR
ChannelMessage.Read.All OR
Group.Read.All OR
Group.ReadWrite.All
Since you have Group.Read.All, that is ALL you need for permissions.
What you need to do is change the base URL to the beta api:
graphClient.BaseUrl = "https://graph.microsoft.com/beta";
UPDATED:
Since now you are saying that you are getting a "Forbidden" error, I think you also have a consent problem.
My guess is that you created & consented you app on one tenant but you are trying to access the data in another tenant. This will give you a forbidden errors. i.e. you created and consented on a dev azure account tenant and are trying to access your work tenant.
If this is the situation you need to:
* Make sure that the setup you azure app to be multi-tenanted
* You have to get your app consented by the target tenant
If you do that and use the beta endpoint I would expect that your example code will start working.
Update2:
Finally got around to trying to do the message list with a application context like you above and I get the same Forbidden error as well from the beta api. From a user context it works fine. So your answer will be to use a user context and not an application context to access this API.
It looks like what you are hitting is a Protected API. So if you want to use this API from an application context, you will have to submit a request to be allowed access to it.

Keycloak - Multi/2FA Factor - OTP - QR Code - Custom Login Screen - Rest API

I have my own Login page where user enters username/password.
This username/password are used to login through Keycloak Rest API.
http://localhost:8080/auth/realms/Demo/protocol/openid-connect/token
input - {username,password,grant_type,client_secret,client_id}
And in response i get access token.
Now i wish to enable Authenticator (Google Authenticator). I have enabled it from backend. Now if user wishes to login thorugh my application, my login page i need to get below details.
1.) Somehow i need to include QR Code that appears on keycloak login page post username/password validation to show on my login screen for the first time login once user enter username/password. So do we have any API which return Keycloak QR code image in response.
2.) Subsequent login i will have OTP field, so need a REST api to pass OTP along with username/password.
Please help with REST API if keycloak has any. Integrating through Javascript.
Similar flow as described in use case 1 here
Just want to use keycloak as a database, doing all operation for me, input will be my screen. I do want redirection of URL's while login in and yet should be standalone deployed.
I've managed to implement this through the rest API of Keycloak. To realize this, you need to extend Keycloak yourself with a SPI. To do this create your own Java project and extend org.keycloak.services.resource.RealmResourceProvider and org.keycloak.services.resource.RealmResourceProviderFactory. You can find more information in the official docs (https://www.keycloak.org/docs/latest/server_development/#_extensions), github examples and other stack overflow posts how to do this.
Once you got this up and running you can implement it like this:
#GET
#Path("your-end-point-to-fetch-the-qr")
#Produces({MediaType.APPLICATION_JSON})
public YourDtoWithSecretAndQr get2FASetup(#PathParam("username") final String username) {
final RealmModel realm = this.session.getContext().getRealm();
final UserModel user = this.session.users().getUserByUsername(username, realm);
final String totpSecret = HmacOTP.generateSecret(20);
final String totpSecretQrCode = TotpUtils.qrCode(totpSecret, realm, user);
return new YourDtoWithSecretAndQr(totpSecret, totpSecretQrCode);
}
#POST
#Path("your-end-point-to-setup-2fa")
#Consumes("application/json")
public void setup2FA(#PathParam("username") final String username, final YourDtoWithData dto) {
final RealmModel realm = this.session.getContext().getRealm();
final UserModel user = this.session.users().getUserByUsername(username, realm);
final OTPCredentialModel otpCredentialModel = OTPCredentialModel.createFromPolicy(realm, dto.getSecret(), dto.getDeviceName());
CredentialHelper.createOTPCredential(this.session, realm, user, dto.getInitialCode(), otpCredentialModel);
}
The secret received with the GET must be send back with the POST. The initial code is the one from your 2FA app (e.g. Google Authenticator). The QR code is a string which can be displayed in an img with src 'data:image/png;base64,' + qrCodeString;
I know this is an old question, but I've recently been looking at something similar, and so thought it would be potentially valuable to share what I have found for others who may be looking into this and wondered what the possibilities are.
TL;DR
You can only really use the existing Keycloak actions to do this or embed the user account management page found at https://{keycloak server URL}/auth/realms/{realm name}/account in an iframe. That's it, I'm afraid. In my opinion it is currently best to just assign actions directly to accounts or use the Credential Reset emails to assign actions; both of these can be done via the Admin API if desired:
Send Credential Reset email containing assigned actions:
https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_executeactionsemail
Set actions directly on the account (include the actions in the requiredActions portion of the user JSON that you send in the body to the endpoint):
https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_updateuser
Background is that as part of a project that I have been working on we wanted to see if we could have an integrated way for users to set up their initial password and OTP device when a new account has been created for them, since the default method of sending them an email from Keycloak using the "Credential Reset" functionality has the limitations that a) it doesn't provide a link to the application itself unless you override the theme, and if you have multiple instances of the application for different users you have no way of knowing which instance to provide the link for, so may have to end up including a list of them, and b) it often doesn't feel truly native to the application, even with changes to the theme. If you're sensible though, I'd suggest you stop and just use this functionality - please see the TL;DR section above for details.
So, in short there is NO API endpoint for receiving a QR code to set up an OTP device. There are two places, however, where the QR code can be retrieved from - the OTP device setup screen when you log in as a user who has had a "Configure OTP" action assigned to their account, and the user's own account management screen.
The first option of the Configure OTP action screen is a non-starter. It only shows up when you log in, and so by definition the user has to log in to Keycloak via the Keycloak login page in order to trigger the page to be displayed. At this point you're already on a Keycloak page instead of one of your app's pages, and so unless you can get very creative with changes to these Keycloak pages via a custom theme, tapping into this page isn't really an option.
The second option is more interesting, but far from ideal. Every user who has logged in has access to an account management page that can be found at https://{keycloak server URL}/auth/realms/{realm name}/account. This page allows you to do things like change your name, password, etc. and it also allows you to add an OTP device if you don't already have one, or delete any existing OTP devices associated with your account. This OTP device tab of the account management page can be reached directly via https://{keycloak server URL}/auth/realms/{realm name}/account/totp.
As I mentioned, there isn't an API that you can access to view the QR code that shows up on this page. The only way it is accessible is via the GET request to https://{keycloak server URL}/auth/realms/{realm name}/account/totp, which returns the HTML for the page I've already mentioned. Okay great, so can we scrape the QR code programmatically and then put it in our own page on our application? Err, no, not really. You see, whilst a lot of the Keycloak API endpoints rightly allow you to send a bearer token (e.g. access token) in the authorization header to access and endpoint, this page will not accept a bearer token as a means of authentication/authorization. Instead it uses a session cookie that is locked down to the Keycloak URL. This cookie is set when you log in to your application via the Keycloak login page, and so is available to this account management page when you navigate to it, having already logged in, and since the account management page uses the same server and domain name as the original Keycloak login page, it has access to the cookie and can let you in. This cookie cannot be sent by your application to e.g. your own REST API to then programmatically call the account management page and scrape the QR code, because your application doesn't have access to it for good security reasons. This might be something you can change in Keycloak somewhere, but if there is I would strongly recommend against changing it.
So if we can't scrape the page from our own server, can we do something on the front-end? Well, as mentioned, your application doesn't have access to the session cookie but if you make a request (e.g. using fetch or axios) in your front-end JavaScript to the account management page then that request will send the cookie along with it, so that could work right? Umm, well actually you will get hit with an error message in this scenario due to CORS. CORS is Cross-Origin-Resource-Sharing and in order to allow the Keycloak page to be accessed then you would have to open up the settings on the server to allow it to be accessed from your website's address. I've seen some articles that look at how you can open up your CORS settings on Keycloak if you wish but I'd be very nervous about doing this. I don't know enough about the internals of Keycloak and how it operates to comment on how much of a security risk this is, but I certainly wouldn't recommend it. There some information here (Keycloak angular No 'Access-Control-Allow-Origin' header is present) on changing the "Web Origins" setting of your application's Keycloak client, but this opens up your application to some serious potential abuse. There is also the MAJOR issue that even if you scraped the QR code, the device isn't actually added to the user's account (even though it appears in the authenticator app) until you enter a code into the page that the QR code is on and click Save. Since there isn't an API endpoint that you can use to complete this operation, I therefore don't think that this option is viable either. I've tried out whether or not you can use the token retrieval endpoint at https://{keycloak server URL}/auth/realms/{realm name}/protocol/openid-connect/token to see if making a request with your username/password/otp code will somehow "register" your device and complete the process, but although you can get a token this way, and it doesn't complain about the otp code, it doesn't actually take any notice of the code because as far as it's concerned the user's account doesn't have a device registered with it. So we have to use the form on the account management page in order to complete this registration process.
So the final way of possibly doing this is.... an iframe. Sorry, yeah it's rubbish but that's all your left with. You can have the iframe point at your account management page, and because the user is logged in then they will be able to see the contents from your application's page. You can use relative positioning, fixed width and height and remove scroll bars to ensure that you ONLY show the QR code and the fields for the one time code, device name, and the Save/Cancel buttons. This, sadly, seems to be the only option at the moment, and due to how nasty and unreliable iframes can be in general - they certainly don't feel native to your application, and you'll need to override your Keycloak theme to get the page in question to look more like your app - I'd recommend steering clear of this and using the standard approach of using Keycloak actions and the Admin API instead.
If you've made it this far, congratulations, you win at Stack Overflow :-)

Save information immediately after Google login in Azure Mobile Services (.NET Back-end)

What I basically want to be able to do is authenticate to azure mobile services (using google or some other provider), and immediately save some of the user information (i.e. email address) on the server.
I know I could call a custom method from the app after authentication, but I was hoping to have some hook to do this straight after the google login on the server side.
Is this possible? How do I do it?!
This is currently only possible in the .NET runtime. If using the Node runtime, you will not be able to do this.
For the .NET runtime, you would want to create a class which inherits from GoogleLoginProvider (I'll call mine CustomGoogleLoginProvider), and then you'll need to override the CreateCredentials method:
public override ProviderCredentials CreateCredentials(ClaimsIdentity claimsIdentity)
{
// grab any information from claimsIdentity which you would like to store
// If you need the access token for use with the graph APIs, you can use the following
string providerAccessToken = claimsIdentity.GetClaimValueOrNull(ServiceClaimTypes.ProviderAccessToken);
// use the access token with HttpClient to get graph information to store
return base.CreateCredentials(claimsIdentity);
}
Then in your WebApiConfig.cs, add the following to the Register() method, immediately after the options object is created:
options.LoginProviders.Remove(typeof(GoogleLoginProvider));
options.LoginProviders.Add(typeof(CustomGoogleLoginProvider));
The CreateCredentials() method gets called immediately before a Mobile Services token is created. At this point, the Google token has been validated, and the claimsIdentity has been populated with whatever Google sent back.
Some information will be available in the claimsIdentity by default, but you may also have information which requires you to call through to Google. You can only do this if you set the proper scopes configured.
If you did want to go the custom API route, you would just need to make a call from your controller:
ServiceUser user = (ServiceUser)this.User;
GoogleCredentials creds = (await user.GetIdentitiesAsync()).OfType<GoogleCredentials>().FirstOrDefault();
string accessToken = creds.AccessToken;
The Node version of getIdentities() is documented here.

Problems configuring user authentication by external API on Symfony2

I have a problem authenticating users for my new Symfony2 application.
This applications gets all the info through an API, so no database is used. When a user goes to login page, he introduce the user and password in the login form. Then, I have to authenticate him using an API call. This API call returns "false" if it's not a user, and return a token key and a token secret if its a correct user. With this token key and secret, during the user session, I can make all the API requests I need for rendering all the pages of the application. Once the user session is over and token key and secret are erased, the user has to login again.
I don't know really how ti implement that. I read this http://symfony.com/doc/current/cookbook/security/custom_provider.html and that http://symfony.com/doc/current/cookbook/security/custom_authentication_provider.html, and I'm still so lost... :(
Can any one help me?
Thank you so much :)
If you want to write custom authentication you have found the correct links. As an example you can see the implementation of the OAuth authorization HWIOAuthBundle. But keep in mind that this type of authentication creates a user on your system. If you do not use a database, you must make a request to the API every time user send a request.
First you need to understand that there is no magic. On every request symfony checks if url matches one of the specified firewalls (see secutity.yml). Listener that fired you can see in the firewall factory. If matches are found, the action switches to the corresponding AuthenticationListener. Listener attempts to authenticate the credewntials by creating Token, which is sended to AuthenticationProvider
$this->authenticationManager->authenticate(new UsernamePasswordToken($username, $password, $this->providerKey));
in AuthenticationProvider
public function authenticate(TokenInterface $token) {
...
}
AuthenticationProvider try to get user via UserProvider. In case of success, Token stored in the session. On subsequent requests, ContextListener comes into play first, checks the session, extract token and send it to AuthenticationProvider similar.
In general terms, the scheme looks like that. More info you can find examining the source code of Symfony Security component.
Really good starting point is a UsernamePasswordFormAuthenticationListener. It just take login and password from request and make simplest UsernamePasswordToken.
protected function attemptAuthentication(Request $request)
{
...
}
Good luck!