How to use Google API auth with flutter for obtaining Client-side Web Application credentials? - google-api

I am trying to use googleapis_auth flutter package to obtain credentials, but stick with var scopes = [...]; what does I need to fill in the var scopes
import "package:googleapis_auth/auth_browser.dart";
...
var id = new ClientId("....apps.googleusercontent.com", null);
var scopes = [...];
// Initialize the browser oauth2 flow functionality.
createImplicitBrowserFlow(id, scopes).then((BrowserOAuth2Flow flow) {
flow.obtainAccessCredentialsViaUserConsent()
.then((AccessCredentials credentials) {
// Credentials are available in [credentials].
...
flow.close();
});
});

Auth scopes express the permissions you request users to authorize for your app. You can get details about what scopes you might need to add to your auth req here
But, googleapis_auth package is meant to be used with web projects only, it can not be used in flutter project.
If you want to implement google auth, try firebase_auth which allows google authentication using firebase backend.

Related

What URL do I use to send users to google oauth2 consent screen

I am trying to write a simple application to access google's api using user authentication tokens and html requests, however I am struggling to find what URL I send users too in order for them to select a profile and sign in.
URL I send users too in order for them to select a profile and sign in.
The thing is you are confusing authorization and authentication. Oauth2 a user can authorize you to access their data, it has nothing to do with logging in to your application that's OpenID connect.
However what you are probably looking for is the oauth2 consent screen This is the screen where the user consents to your application accessing their data.
https://accounts.google.com/o/oauth2/auth?client_id={clientid}&redirect_uri={redirectURI}&scope={scope}&response_type=code
Remember this is only the first step if they consent then you will be given an authorization code your application must then exchange the authorization code for an access token which you can use to access the api.
You may find this video helpful in understanding the fill Oauth2 dance. Understanding Google OAuth 2.0 with curl
If you are looking to login a user and check their profile something like this would be better
[GoogleScopedAuthorize(PeopleServiceService.ScopeConstants.UserinfoProfile)]
public async Task UserProfile([FromServices] IGoogleAuthProvider auth)
{
var cred = await auth.GetCredentialAsync();
var service = new PeopleServiceService(new BaseClientService.Initializer()
{
HttpClientInitializer = cred
});
var request = service.People.Get("people/me");
request.PersonFields = "names";
var person = await request.ExecuteAsync();
return View(person);
}
The full tutorial and companion video can be found here Asp .net core 3 and Google login

How to use openid connect with flutter on spring security

I created a spring boot service that is secured by the spring-security-keycloak-adapter. As the service already knows about the (keycloak) identity provider, I don't see any point in sending the issuerUrl and clientId to the mobile client to login directly into keycloak. Instead, I want to simply call the loginurl of the service in a webview on the client. In my understanding spring should redirect to keycloak and in the end return the token.
Unfortunately all flutter packages require the clientId and issuerUrl for the oauth process
I alread tried the openid_client package for flutter
As your can see in the following code example from the official repository it requires the clientId and issuerUrl
// import the io version
import 'package:openid_client/openid_client_io.dart';
authenticate(Uri uri, String clientId, List<String> scopes) async {
// create the client
var issuer = await Issuer.discover(uri);
var client = new Client(issuer, clientId);
// create an authenticator
var authenticator = new Authenticator(client,
scopes: scopes,
port: 4000);
// starts the authentication
var c = await authenticator.authorize(); // this will open a browser
// return the user info
return await c.getUserInfo();
}
Full disclosure: I didn't write Flutter, but I did write some of the related client code for Spring Security.
Why issuerUri? The reason for this is likely for OIDC Discovery. You can use the issuer to infer the other authorization server endpoints. This cuts down on configuration for you: You don't need to specify the token endpoint, the authorization endpoint, and on and on. If you supply only the issuer, then flutter figures out the rest.
Note that with Spring Security, this is just one configuration option among multiple, but something needs to be specified either way so the app knows where to go. I can't speak for flutter, but it may just be a matter of time before it supports more configuration modes.
Why clientId? This is a security measure and is required by the specification. If someone is calling my API, I want to know who it is. Additionally, authorization servers will use this client_id to do things like make sure that the redirect_uri in the /authorize request matches what is configured for that client_id.

Google Admin Setttings API connection for .NET

I've been working with the Google directory API for quite some time now.
However, I need to update SSO settings in the admin settings section of Google. Yes, they say it will be deprecated at some point, but according to a google employee, it's going to be a while before a new API is available and then the old one will be removed.
First, if there is a NUGET package out there, please let me know. I can't seem to find anything that works with the admin settings API: https://developers.google.com/admin-sdk/admin-settings/
My first attempt is getting the SSO settings in Google.
I can use postman to pull this information so I know the API works.
However, I'm running into two issues:
How can I authenticate using the service certificate that I use in the apis.google.directory class?
Anticipating, how do I request access to the admin settings? In directory API, I have the scope enum to select from. If I'm making a manual connection to the API I assume I'll need to call this by hand?
Code
var certificate = new X509Certificate2(serviceAccountCertPath,
serviceAccountCertPassword,
X509KeyStorageFlags.Exportable);
// below the scopes are going to get in my way, right? What is the scope process I need to do for this manually?
credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { DirectoryService.Scope.AdminDirectoryUser,
DirectoryService.Scope.AdminDirectoryGroup,
DirectoryService.Scope.AdminDirectoryOrgunit},
User = _szAdminEmail
}.FromCertificate(certificate));
// I'm not seeing anyway to call the above credentials
using (HttpClient client = new HttpClient())
{
// client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
client.BaseAddress = new Uri(#"https://apps-apis.google.com/a/feeds/domain/2.0/[mydomain]/sso/general");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//client.DefaultRequestHeaders.
HttpResponseMessage response = client.GetAsync("api/Values").Result; // Blocking call!
var products = response.Content.ReadAsStringAsync().Result;
return products.ToString();
}
The admin settings API does not appear to support service account authentication you will need to use Oauth2. Admin Settings Oauth
Your not going to be able to use it very easily using the Google .net client library as that library was designed for use with the Google discovery apis. I dont think the Admin Settings API is a discovery api. You might be able to use the old gdata library for it I am not sure if one exists I have not been able to find it on nuget. If you do find it the old gdata library doesn't support oauth2 which means that you will need to use the new library for that and plug in the gdata library after.
I have only done this before using the Google contacts api I have a tutorial here on how i did it it may help you here
Auth
string clientId = "xxxxxx.apps.googleusercontent.com";
string clientSecret = "xxxxx";
string[] scopes = new string[] { "https://www.googleapis.com/auth/contacts.readonly" }; // view your basic profile info.
try
{
// Use the current Google .net client library to get the Oauth2 stuff.
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret }
, scopes
, "test"
, CancellationToken.None
, new FileDataStore("test")).Result;
// Translate the Oauth permissions to something the old client libray can read
OAuth2Parameters parameters = new OAuth2Parameters();
parameters.AccessToken = credential.Token.AccessToken;
parameters.RefreshToken = credential.Token.RefreshToken;
RunContactsSample(parameters);
If you cant find the gdata library for it you may have better luck just using the library for authencation and then code the rest of the calls yourself. It returns xml not json.

Google calendar API - How to make a request without having to prompt a login?

I have a simple question:
I am developing a website that needs full authorisation to make requests to a Google calendar. I manage to do all the requests I need with javascript from a web server and it works, but I need to be logged into my google account for it to work. This caused a problem for other users that use my website because the request doesn't work if they are not logged into MY google account.
I understand why it doesn't work, my question is How can I do for my website to get full access granted for use the google calendar without having to log into my google account, even better if nobody had to log into a Google account to perform the task??
The form of login you are currently using is called Oauth2. It requires that a user authenticate access.
What you should be using is a service account. Service accounts are pre authorized. You will need to share your personal calendar with the service account then it will be able to access it.
The only drawback is that service account authentication is not supported by JavaScript you will need to switch to a server sided language like node.js for example.
'use strict';
const {google} = require('googleapis');
const path = require('path');
/**
* The JWT authorization is ideal for performing server-to-server
* communication without asking for user consent.
*
* Suggested reading for Admin SDK users using service accounts:
* https://developers.google.com/admin-sdk/directory/v1/guides/delegation
*
* See the defaultauth.js sample for an alternate way of fetching compute credentials.
*/
async function runSample () {
// Create a new JWT client using the key file downloaded from the Google Developer Console
const client = await google.auth.getClient({
keyFile: path.join(__dirname, 'jwt.keys.json'),
scopes: 'https://www.googleapis.com/auth/drive.readonly'
});
// Obtain a new drive client, making sure you pass along the auth client
const drive = google.drive({
version: 'v2',
auth: client
});
// Make an authorized request to list Drive files.
const res = await drive.files.list();
console.log(res.data);
return res.data;
}
if (module === require.main) {
runSample().catch(console.error);
}
// Exports for unit testing purposes
module.exports = { runSample };
Code ripped from smaples jwt

Integration tests for web api with Azure AD

I am working on a webapi webservice that is proteted by Azure Active Directory. The webservice cumminucates heavily with Office 365 (SharePoint / Yammer) based on the user that is signed in.
To test the web api endpoints I am writing an Console App that let me sign in with my AAD credentials and then calls the endpoints. It works, but looking for something to replace this way of testing the web api. Would be great if it’s more repeatable and that I don’t have to fill in my credentials each time. I was looking for a unit test project but can’t get the Azure AD sign in to work.
Any tips how to make this easier?
The easiest way would be to define the test runner as an application in Azure AD and have it call the API with its own client id and secret.
To do that there are a few things you would need to do:
Add appRoles to your API in its manifest in Azure AD. These are application permissions.
Define your test runner, and have it require the necessary application permissions for your API.
In your test runner you should now be able to get an access token with the client id and secret of the test runner, no user authentication required.
Some setup is needed for app permissions on the API side as well, authorization must also look at the role claims.
You can find an example for defining app permissions and also handling them here: http://www.dushyantgill.com/blog/2014/12/10/roles-based-access-control-in-cloud-applications-using-azure-ad/.
More on defining app permissions: https://stackoverflow.com/a/27852592/1658906.
More info on the application manifest in AAD: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-application-manifest.
EDIT: If you must make calls on behalf of the user in the API, then this of course won't work.
In that case, I would suggest creating a user account with the necessary access for the purpose of running the tests. It would be best not to hard-code its credentials, but store them elsewhere.
If you don't want to "fill in my credentials each time", one workaround is using the Resource Owner Password Credentials Grant flow. This flow is flexible to gain a token easily. In the Console App, you could directly use user account and password to get the access token for your protected web API . The code below is for your reference :
static void Main(string[] args)
{
test().Wait();
}
public static async Task test()
{
using (HttpClient client = new HttpClient())
{
var tokenEndpoint = #"https://login.windows.net/a703965c-e057-4bf6-bf74-1d7d82964996/oauth2/token";
var accept = "application/json";
client.DefaultRequestHeaders.Add("Accept", accept);
string postBody = #"resource=https%3A%2F%2Fgraph.microsoft.com%2F //here could be your own web api
&client_id=<client id>
&grant_type=password
&username=nanyu#xxxxxxx.onmicrosoft.com
&password=<password>
&scope=openid";
using (var response = await client.PostAsync(tokenEndpoint, new StringContent(postBody, Encoding.UTF8, "application/x-www-form-urlencoded")))
{
if (response.IsSuccessStatusCode)
{
var jsonresult = JObject.Parse(await response.Content.ReadAsStringAsync());
var token = (string)jsonresult["access_token"];
}
}
}
}
But the problem is that flow will expose the username and password directly in the code, it brings potential attack risk as well and we will always avoid handling the user credential directly. So make sure you just use this flow for testing in a secure environment. You could refer to this article for more details.

Resources