My scenario involves two service accounts, namely S1 and S2.
S2 was granted domain-wide access to a Google Workspace.
I'd like to have S1 impersonate S2 (already have the "Service Account Token Creator role" on S1) and use its permissions to retrieve some information regarding Google Workspace using S2's access.
Is it possible to delegate authority to S1?
Edit:
Johannes Passing solution did the trick, still feels like somewhat of a workaround, opened an issue on google-api-dotnet-client to add such a functionality.
Yes, that's possible if S2's client ID has been configured for domain-wide delegation:
Create a JWT assertion with:
iss set to S2's email address
sub set to the Workspace user's email address
scope set to the scopes you whitelisted for S2's client ID and domain-wide delegation
As S1, call projects.serviceAccounts.signJwt on S2 to sign the assertion with S2's key. As a result, you get a signed JWT assertion. For this to work, S1 must have the Service Account Token Creator role on S2.
Post the assertion to https://oauth2.googleapis.com/token. As a result, you get an access token for the Workspace user.
Related
I have a setup like this:
Back-end REST API application - Single Instance running in Cloud Server - Let's call it as A
Public Users` Mobile app & browser clients - Let's call them together as X
We already are using Keycloak for Identity and Access Management. As per the current setup,
X to A uses Password grant flow, that is – a client is created in Keycloak with Client-Type as Public for user management and auth of X to A.
Now, we have to introduce new layer of back-end app, that is,
Back-end REST API application - Multiple Instances running in On-prem Servers across different physical locations - Let's call them together as B.
Now, both B and X both are clients of A, [i.e. A serve both B and X].
Please clarify:
Should I create another type of client in the same realm for B, like below?
B to A: Client credentials grant flow i.e. I have to create another Client-Type as Confidential for B to A, to configure a service-account for each of the instances of B.
If yes, please guide me on how to configure both Auth flows in A i.e. A has to auth both B and X.
I feel like this one as a bad idea - Using the existing setup as it is, which is explained below.
As per the new business logic,
X logs-in the app (mobile/web app) using username and password and calls an API of A to generate a QR Code, which will contain the hash of the user's (X's) access token and some other info.
A stores both hash and access token of X in the database
B gets the hash of the access token used by X to access A, from the QR Code scanned by the user. B uses the hash to validate the authenticity of the QRCode, by calling an API of A
As mentioned in the above business logic, if needed, A can expose an API, where the above said user access token can be retrieved through a get request, by sending the hash as a request header param or query. This token can be further used by B for further API calls to A.
I think that the above idea is bad, because, we are not supposed to send the user access token over the internet, even if there is a SSL/TLS connection between B and A.
Can the Client-Type, Bearer-Only be used in this scenario between B and A? If yes, Please guide me on this.
As you are having both Public and On prem services as clients, I would suggest the following:
As you said, X as public client shall use Password grant
B should use Client Credentials mechanism to get itself authenticated with Keycloak. Keycloak will provide it the access token through ${kc.realm-url}/protocol/openid-connect/token endpoint. This access token can be sent to A.
"A" should also be a registered client with its own credentials.
When "A" receives request from X or B, it should use a mechanism called Token verification through Introspection endpoint where it will get the token verified by calling Keycloak.
Introspection endpoint expects access token, client id and client secret.
This way, A can be sure that the token received by it is indeed issued by Keycloak.
I'm having hard time understanding SSO. Anywhere I read there are those high-level explanations of how the site that authenticates the user "passes the token" to the site that was originally accessed or that it knows that the user has already been authenticated if you access it later on. But I am still interested in the details of how those things are being accomplished.
Let's assume there are two sites, A and B, and a site X that is responsible for the authentication that A and B use.
Here are some questions that I can't find answers for:
if I access A and are then redirected to X to input my credentials, I get authenticated and then how exactly does X let A know that I am who I am? I know there is a token involved - how is this token passed exactly? Is it passes in a query string/body/header of a request that redirects me back to site A?
What happens after the A is notified that I have been authenticated? Does it issue me a cookie? Or am I holding this token somehow? How do A know with every subsequent request that I am who I am?
if I got successfully authenticated accessing site A and then try to access site B, I get redirected to site X - how does the site X know that I have already been authenticated? I guess I don't pass any cookies, do I? Did I get a cookie from X when authenticating there?
The reason it's confusing has to do with ambiguity of term "SSO". Your questions are good but the answers would depend on how SSO is implemented, there's not a one size fits all solution. We'll answer your questions with SAML as the protocol, it's often used to implement SSO between web apps:
A = service provider, X = identity provider. These are "roles" a service (or an application) might play in SAML. The identity provider sends a SAML response to the service provider after the identity provider authenticates the user. A so-called binding is a set of rules in SAML spec that determines how the response is formatted and transmitted from identity provider to the service provider. In Web Browser SSO profile of SAML, the HTTP-POST binding mandates that the response is sent via, well, POST over HTTPS. The response contains an assertion, sometimes referred to as a SAML "token". The assertion is a container for statements (aka claims) made by the SAML authority (your X) with respect to authenticated entity. For example, if the identity provider authenticates user "bee", the assertion sent to the service provider may contain bee's first name, last name, user id and so on.
Typically you'll get a cookie. The service provider A will create a "local" (to A) session and drop a cookie with session ID (or whatever session pointer) to associate the user agent with the session. On subsequent requests to A, A knows you on the basis of the cookie which maps to a session in A. The session holds the authenticated context established, say, the user id of user "bee" that came from the SAML response in step 1.
Also via cookies (usually). When you're authenticated with the identity provider X, it issues its own cookie. You have one cookie for X, one for A, one for B, ...
We say "usually" because the state management (how does A or X know it's you) is not part of the SAML spec. If an identity provider comes up with an exotic state management scheme, say, fingerprinting your browser and relying on that fingerprint as your authenticated context/session id, that's still okay with SAML from a protocol perspective. Only step 1 is formally described in the protocol, steps 2 and 3 are up to the implementation. In practice, cookies have a very short list of alternatives and most apps use cookies.
Take a look at SAML Technical Overview, it does a good job of addressing the essence of this Q&A.
I have a question regarding Keycloak and obtaining an Access Token.
Our setup is as follows:
· users are created and maintained in Keycloak
· resources, policies and permissions are also maintained in Keycloak
Our use case is:
As a third party application, I want to obtain authorization information (e.g. resource- and scope-based permissions) for a specific user by only providing the username to Keycloak, so I can allow or prohibit further actions.
To be more specific:
In our application the need to validate each request to other services based on the access token.But we have only the user name with us.
The question is now:
> How can we obtain an access token for the user by only knowing the username ?
>
Is there a solution to obtain an access token for such a user?
You don't specify in your question if the current user is logged in. Are you validating user specific actions, or you want to retrieve user roles for the application instead?
The user is logged in and he is performing some action
I suppose you're using some keycloak adapter. Then just retrieve the session object and you should have the extra info somewhere in there.
If not, you can just parse the request yourself. When using OpenId Connect, the access token is always sent for each of the requests, in the Authorization header. The token is base64 encoded, you can decode the token yourself.
The application is performing some action for some registered user, without him logged in
User access tokens are meant to provide permissions for users. As you say in your question: As a third party application, I want... so here you are not acting as a logged user, but as an application, so you need to go with client credentials instead. Just give the client permissions to list all the users and their roles (probably it's enough with the view-users role, see the link below) and log in with client credentials grant. Then you can handle fine grained permissions in your application business logic.
See also:
Keycloak Client Credentials Flow Clarification
Keycloak spring security client credential grant
How to get Keycloak users via REST without admin account
For those who really needs to impersonate a user from a client, there is a new RFC for this : token-echange.
Keycloak loosely implement it at the time of this answer
See particularly https://www.keycloak.org/docs/latest/securing_apps/#direct-naked-impersonation
I'm trying to figure out how to use the Azure Graph API to query a user's full name (first and last) from a given username. I understand I can do this with the following Graph API call...
https://graph.windows.net/myorganization/users/{user_id}?api-version
However, I am not sure how I go about getting an access token to use with this, because this process will be called without a user logging in, which is usually how we obtain an access token.
Is there anyway I can pass a username/password to a given URL using cURL or something and obtain an access token that way, so it is done behind-the-scenes?
There are two main authentication methods which are supported by OAuth 2:
Authorization Code Grant Flow
Client Credentials Grant Flow
The first flow requires a user agent to be present to sign into the client service and results in a delegated token. The second method does not require a user to sign in, as it only authenticates using the client secret; this results in an app only token.
If you want to create a background service that captures data from the AAD Graph API, you can absolutely do this using the Client Credentials Grant Flow, which does not require a user to be present at any point during the authentication flow.
You simply need to configure your application to to have app only scopes. Read here: Permission scopes | Graph API concepts. App only scopes all require tenant administrators to consent to the application in order to get access to data.
Finally, I feel I must mention that there is another less used flow specified in the OAuth 2 spec: Resource Owner Password Credentials Grant. This flow specifies how a client application who has knowledge of a user's username and password could directly pass those parameters and get an access token on behalf of the user. However using this flow is not good practice at all.
The resource owner password credentials grant type is suitable in
cases where the resource owner has a trust relationship with the
client, such as the device operating system or a highly privileged
application. The authorization server should take special care when
enabling this grant type and only allow it when other flows are not
viable.
We support this in our V1 endpoint, but not in our new V2 endpoint. You can read this blog to learn more.
I am in the process of implementing IdentityServer3 in our company but I have hit a blank around how to handle client to client authorization and would appreciate any pointer in the right direction.
This is a summary of our requirements:
We have multiple web site clients that our users access. These are configured using the AuthorizationCode flow. Lets call these WebSiteClientA, WebSiteClientB.
We have multiple WebAPI clients as back end services that could be accessed by either a client (WebSiteClientA, WebSiteClientB) or a user (who has access to WebSiteClientA or WebSiteClientB). Lets call this WebAPIClientA.
Note: Our company owns the users identity as well as all clients.
Initially I though we could configure WebAPIClientA using the ClientCredentials flow. Then WebSiteClientA \ WebSiteClientB would be configured with the client credentials for WebAPIClientA and could generate an access token when it required access to WebAPIClientA, or alternatively generate an access token with limited scopes and hand this access token to the user so the user can access WebAPIClientA directly from the client side.
This would meet almost all our our requirements except 1 big one, we also want to be able to manage what scopes a client has access to for another client and with the approach of using the ClientCredentials flow anyone with the client credentials would be able to generate access tokens for all scopes under that client. ie WebSiteClientA should be able to generate an access token for WebAPIClientA with read & write scopes but WebSiteClientB should only be able to generate an access token for WebAPIClientA with the read scope.
In my mind the client\identity server conversation would be:
WebSiteClientA makes a request to the identity server for an access token to WebAPIClientA for scope X and provides the client secret for WebSiteClientA. The identity server then says yes, you are WebSiteClientA and we can see from our records you have access to WebAPIClientA with scope X, here is an access token.
Is this possible or am I looking at this in the completely wrong way and there is maybe a better approach to meeting the requirements?
It sounds like you're talking about two things.
The first is that in the APIs you need the user's id. To obtain the user id you have a decision if you want to build a trusted subsystem, or if you don't want a trusted subsystem (in the sense that your APIs trust or don't trust the MVC client to pass along the user's identifier). If you do a trusted subsystem, then the client credentials flow from the MVC client to the API is fine. If you don't want a trusted subsystem, then you need the MVC client to obtain an access token for the user (via implicit or hybrid flow).
The second issue you're asking about is if you can control the scopes each client is allowed to request, and you can via the AllowedScopes configuration property (or whatever it's called) on the client configuration. This setting is orthogonal to the first issue mentioned above.