How to provide credentials for Google Apps user creation using JAVA API - google-oauth

From the Google Documentation I understood that the email quota is not used anymore. I'm OK with that, but the question is how to provide credentials for user creation in Google Apps. Currently I'm doing it like that:
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(transport)
.setJsonFactory(jsonFactory)
.setClientSecrets(adminid, adminpwd)
.build();
But I'm receiving 401 Unauthorized.

Where's your access token? Try
credential.refreshToken();
accessToken = credential.getAccessToken();
credential.setAccessToken(accessToken);
You'll probably want to retrieve a refresh token too. It may be cleaner to build your credentials with the tokens. Refer to the docs here or here.

Related

Is there anyway/endpoint to create access_token in code for Dropbox SDK authorization?

I am using dropbox javascript sdk for file uploads using following end points.
For file below 150MB
/upload
For file above 150MB
/files/upload_session/start
/files/upload_session/append_v2
For Authorization, I am using the following code for now.
const ACCESS_TOKEN = 'my_access_token_created_manualy_from_app_console';
var dbx = new Dropbox.Dropbox({ accessToken: ACCESS_TOKEN, refresh_token });
Now I don't want to go to the app console every now and then to get access token.
Is there any way I could handle it in my code? Any API/ajax request to get access token in response to app_key and app_secret?
Getting a Dropbox access token for a user's account always requires some initial manual interaction from the user to authorize the app in some way. This cannot be done entirely programmatically. For the developer's own account, such as in your case, you can generate an access token on the App Console. For arbitrary end-users, this is instead processed via the OAuth app authorization flow.
You can refer to the OAuth Guide and authorization documentation for more information. For the Dropbox JavaScript SDK in particular, there's an example of processing the OAuth flow here.

Identity Server 4, External providers and Web API

I’m in process of developing system which consists from such parts:
- Some services under gateway (Ocelot)
- Mobile client (iOS)
- Identity Server 4
Mobile client hasn’t been prepared yet, so I use Postman for emulating requests from it. My problem is implementation of Authentication with External providers, like Google. It’s my first experience of using IS 4, so I have some misunderstanding and difficulties. Excuse me, if my question is too abstract or if I miss smth obvious.
I successfully deployed IS 4 using all this tutorials and it works with Password Credentials flow in a proper way: I request IS for access token, sending user credentials, it returns token and I can successfully use it for access to my API methods.
Situation with External Providers are different. I’ve overviewed this tutorial (https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/google-logins?view=aspnetcore-3.1) and some other and add code from it to the IS project. I can successfully log in with Google, using a button on that IS4 web-page which goes with IS 4 Quickstart UI template. But no chance to work with API. As I understand in such workflow client-app should go for a token not to my IS as in example with a local user, but to the Google Auth provider. And I emulated it with Postman and got a strange access_token which has no data and it_token which contains username, email and so on. I try to use this id_token with requests to my API. The result is always 401.
Where I’m wrong? How should I build requests to API with token from Google? Or I have misunderstanding and there should be another flow: client goes to IS with specific request, IS goes to Google and then returns proper token to Client?
Here is configuration of authecation on the side of Web API app:
private void ConfigAuthentication(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.Audience = "k_smart_api";
});
}
Here is config of Google-Auth on the side of IdentityServer:
services.AddAuthentication().AddGoogle(opts => {
opts.ClientId = "My google client Id";
opts.ClientSecret = "my google client secret";
opts.SignInScheme = IdentityConstants.ExternalScheme;
opts.SaveTokens = true;
});
This is how I get Access Token:
postman exampple
The tokens you get back from Google, is only used to Authenticate the user in Identity Server. Then after Identity Server receives those tokens, it sign-in the user and create new tokens (ID+access) that are passed to your client. you should look at using the authorization code flow in your client to authenticate the user and to get the tokens. then use the access token received to access your API.
do remember that the tokens received from Google are not used to give access to your APIs.

Google Photos API - authentication

I'm trying to get list of my shared albums from Google Photos.
I found a enable Photos API in Google Developers Console.
HTTP GET:
https://content-photoslibrary.googleapis.com/v1/sharedAlbums?key=AIzaSyCkXXXXXXXXXXXXXZiOSe9IiyM8E
RESULT:
{ "error": { "code": 401, "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.", "status": "UNAUTHENTICATED" } } 1
Configuration in developers console:
Please, what I'm doing wrong? Thank you.
Google API need an access token to make sure that the user has the permission to access the feature. Access token is just like cookie that should be send together with the request.
Usually you will need so many setup to get the access token with your own code. But there are a client library that can help you access Google API with small setup.
Access token also has a lifetime, so if you don't use the library you will need to manually refresh the token.
You need to configure OAUth 2.0 credentials (client ID and secret) and not an API key. More details are in the developer documentation here: https://developers.google.com/photos/library/guides/get-started#request-id
The Google Photos library API acts on behalf of a user, that's why you need to authenticate via OAuth 2.0. As part of this request you also need to specify a scope for your users to accept, see this page for more details: https://developers.google.com/photos/library/guides/authentication-authorization
I've been working on a python project to backup google photos library and album info. you can probably modify it to do exactly what you want. It is fully working but does not currently distinguish between shared and private albums.
https://github.com/gilesknap/gphotos-sync
In particular, see https://github.com/gilesknap/gphotos-sync/blob/master/gphotos/authorize.py which handles authentication and authorization for any Google service (it also handles storing the token and refreshing the token).

Get UserInfo from ADFS in UWP with ADAL

I am trying to authenticate the user with ADFS and I am using ADAL. Authetication seems to work since I can get the AccessToken. The problem is that looking at the code authResult contains a UserInfo where all properties (for instance GivenName or FamilyName) are null.
AuthenticationContext authContext = null;
AuthenticationResult authResult;
try
{
authContext = new AuthenticationContext(authority, false);
authResult = await authContext.AcquireTokenAsync(resource, clientId, new Uri(returnUri),
new PlatformParameters(PromptBehavior.Auto, false));
}
Those values are null because of ADFS configuration? I noted that decoding the AccessToken returned I can read User information. But I don't think that decoding the JWT Token is the right way to achieve those information. Do you have a better suggestion?
I have also seen people getting information by using claims, but I don't know exactly how to use it on UWP, since all the sample I found used
ClaimsPrincipal claimsPrincipal = System.Threading.Thread.CurrentPrincipal as ClaimsPrincipal;
But System.Threading.Thread is not available on UWP.
Normally, the access_token is used in Oauth and OpenID connect scenarios and intended to be consumed by the resource. To identify the user we should use the id_token( verify the token and extract the claims abut user by decoding the token). Please refer below about the usage of tokens:
id_token: A JWT token used to represent the identity of the user. The
'aud' or audience claim of the id_token matches the client ID of the
native or server application.
access_token: A JWT token used in Oauth and OpenID connect scenarios
and intended to be consumed by the resource. The 'aud' or audience
claim of this token must match the identifier of the resource or Web
API.
refresh_token: This token is submitted in place of collecting user
credentials to provide a single sign on experience. This token is
both issued and consumed by AD FS, and is not readable by clients
or resources.
And you can refer the link below about the native client to web API scenario for ADFS:
AD FS Scenarios for Developers - Native client to Web API
Depending on the ADFS version of your server. If your company is using Windows Server 2012 R2, then it is ADFS 3.0. I did successfully integrate with SSO login created by the admin of company I am working in. You should refer to this article before venturing in : https://learn.microsoft.com/en-us/previous-versions/adfs-windows-server-2012r2/dn660968(v=msdn.10). Note : you don't even need to make a web api of ToDoList.
using only GetAuthorizationHeader() and authenticationContext.AcquireTokenAsync(), you could obtain the token by asking the user to authorize their credentials and decrypt the receive token.
This is sample of code I did:
authority = https://contoso.com/adfs/ls (Endpoint from the ADFS metadata)
resourceURI = https://localhost:44300/ (Relying party, ask your ADFS admin to register)
clientID = it is recommended to use Package.appmanifest's package name from Packaging tab. As long as it is a unique ID.
clientReturnURI = use the following code to obtain the clientReturnURI (also available in the article in the link) :
string clientReturnURI = string.Format("ms-appx-web://Microsoft.AAD.BrokerPlugIn/{0}",WebAuthenticationBroker.GetCurrentApplicationCallbackUri().Host.ToUpper());
AuthenticationContext ac = new AuthenticationContext(Authority_Uri, false);
AuthenticationResult ar = await ac.AcquireTokenAsync(resourceURI, GlobalVar.clientID, new Uri(clientReturnURI), new PlatformParameters(PromptBehavior.Always, true));
var jwt = new JwtSecurityToken(ar.AccessToken);
string unique_name = jwt.Claims.First(c => c.Type == JwtRegisteredClaimNames.UniqueName).Value;
You can replace JwtRegisteredClaimNames.UniqueName with anything else. It depends what info/claims that is available in the access token. You should inspect the available info in the jwt by placing breakpoint at var jwt. Or you can decrypt the access token in the AuthenticationResult.AccessToken in this website :
https://jwt.ms/
Lastly, you need to install certificate from your ADFS admin and install the certificate across your web and UWP server to allow the application able to trust execute the actions.

OWIN/OAuth2 3rd party login: Authentication from Client App, Authorization from Web API

I am trying to create a Web API that allows the API's clients (native mobile apps) to login using a 3rd party cloud storage provider. I'm using the following general flow from Microsoft:
Here is what I am trying to achieve:
I am using the default ASP.NET Web API Visual Studio template with external authentication, along with the OWin.Security.Providers Nuget package for Dropbox login functionality, and the existing built-in login functionality for Google (Drive) and Microsoft (OneDrive).
The issue I'm having is that the built-in functionality all seems to do the authentication and authorization as part of one flow. For example, if I set up the following in Startup.Auth.cs:
DropboxAuthenticationOptions dropboxAuthOptions = new DropboxAuthenticationOptions
{
AppKey = _dropboxAppKey,
AppSecret = _dropboxAppSecret
};
app.UseDropboxAuthentication(dropboxAuthOptions);
... and navigate to this url from my web browser:
http://<api_base_url>/api/Account/ExternalLogin?provider=Dropbox&response_type=token&client_id=self&redirect_uri=<api_base_url>
I am successfully redirected to Dropbox to login:
https://www.dropbox.com/1/oauth2/authorize?response_type=code&client_id=<id>&redirect_uri=<redirect_uri>
... and then after I grant access, am redirected back to:
http://<api_base_url>/Help#access_token=<access_token>&token_type=bearer&expires_in=1209600
... as you can see the token is part of that, so could be extracted. The problem is that the client needs to be the one navigating to Dropbox and returning the authorization code back up to the Web API, and the Web API would send the authorization code back to the third party to get the token which would then be returned to the client... as shown in the diagram above. I need the ExternalLogin action in the AccountController to somehow retrieve the Dropbox url and return that to the client (it would just be a json response), but I don't see a way to retrieve that (it just returns a ChallengeResult, and the actual Dropbox url is buried somewhere). Also, I think I need a way to separately request the token from the third party based on the authorization code.
This post seems a little similar to what I am trying to do:
Registering Web API 2 external logins from multiple API clients with OWIN Identity
... but the solution there seems to require the client to be an MVC application, which is not necessarily the case for me. I want to keep this as simple as possible on the client side, follow the flow from my diagram above, but also not reinvent the wheel (reuse as much as possible of what already exists in the OWIN/OAuth2 implementation). Ideally I don't want the client to have to reference any of the OWIN/OAuth libraries since all I really need the client to do is access an external url provided by the API (Dropbox in my example), have the user input their credentials and give permission, and send the resulting authorization code back up to the api.
Conceptually this doesn't sound that hard but I have no idea how to implement it and still use as much of the existing OAuth code as possible. Please help!
To be clear, the sample I mentioned in the link you posted CAN be used with any OAuth2 client, using any supported flow (implicit, code or custom). When communicating with your own authorization server, you can of course use the implicit flow if you want to use JS or mobile apps: you just have to build an authorization request using response_type=token and extract the access token from the URI fragment on the JS side.
http://localhost:55985/connect/authorize?client_id=myClient&redirect_uri=http%3a%2f%2flocalhost%3a56854%2f&response_type=token
For reference, here's the sample: https://github.com/aspnet-security/AspNet.Security.OpenIdConnect.Server/tree/dev/samples/Mvc/Mvc.Server
In case you'd prefer a simpler approach (that would involve no custom OAuth2 authorization server), here's another option using the OAuth2 bearer authentication middleware and implementing a custom IAuthenticationTokenProvider to manually validate the opaque token issued by Dropbox. Unlike the mentioned sample (that acts like an authorization proxy server between Dropbox and the MVC client app), the JS app is directly registered with Dropbox.
You'll have to make a request against the Dropbox profile endpoint (https://api.dropbox.com/1/account/info) with the received token to validate it and build an adequate ClaimsIdentity instance for each request received by your API. Here's a sample (but please don't use it as-is, it hasn't been tested):
public sealed class DropboxAccessTokenProvider : AuthenticationTokenProvider {
public override async Task ReceiveAsync(AuthenticationTokenReceiveContext context) {
using (var client = new HttpClient()) {
var request = new HttpRequestMessage(HttpMethod.Get, "https://api.dropbox.com/1/account/info");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.Token);
var response = await client.SendAsync(request);
if (response.StatusCode != HttpStatusCode.OK) {
return;
}
var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
var identity = new ClaimsIdentity("Dropbox");
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, payload.Value<string>("uid")));
context.SetTicket(new AuthenticationTicket(identity, new AuthenticationProperties()));
}
}
}
You can easily plug it via the AccessTokenProvider property:
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions {
AccessTokenProvider = new DropboxAccessTokenProvider()
});
It has its own downsides: it requires caching to avoid flooding the Dropbox endpoint and is not the right way to go if you want to accept tokens issued by different providers (e.g Dropbox, Microsoft, Google, Facebook).
Not to mention that if offers a very low security level: since you can't verify the audience of the access token (i.e the party the token was issued to), you can't ensure that the access token was issued to a client application you fully trust, which allows any third party developer to use his own Dropbox tokens with your API without having to request user's consent.
This is - obviously - a major security concern and that's why you SHOULD prefer the approach used in the linked sample. You can read more about confused deputy attacks on this thread: https://stackoverflow.com/a/17439317/542757.
Good luck, and don't hesitate if you still need help.