Using php to create authenticated request to an google endpoints - rest

I am trying to figure out a way to create a JWT and sign it with the service account's private key and
Send the signed JWT in a request to the Google API Endpoint. I have search out there are numerous of the library available for Java and Python but is there any library available for PHP?
will need to follow Google’s Cloud Endpoints standard for authentication between services. Below there is an example of how we can access java, which I wanted to accomplish in PHP?
public static String generateJwt(final String saKeyfile, final String saEmail,
final String audience, final int expiryLength)
throws FileNotFoundException, IOException {
Date now = new Date();
Date expTime = new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(expiryLength));
// Build the JWT payload
JWTCreator.Builder token = JWT.create()
.withIssuedAt(now)
// Expires after 'expiraryLength' seconds
.withExpiresAt(expTime)
// Must match 'issuer' in the security configuration in your
// swagger spec (e.g. service account email)
.withIssuer(saEmail)
// Must be either your Endpoints service name, or match the value
// specified as the 'x-google-audience' in the OpenAPI document
.withAudience(audience)
// Subject and email should match the service account's email
.withSubject(saEmail)
.withClaim("email", saEmail);
// Sign the JWT with a service account
FileInputStream stream = new FileInputStream(saKeyfile);
GoogleCredential cred = GoogleCredential.fromStream(stream);
RSAPrivateKey key = (RSAPrivateKey) cred.getServiceAccountPrivateKey();
Algorithm algorithm = Algorithm.RSA256(null, key);
return token.sign(algorithm);
}

Using PHP to create authenticated request to an Google Endpoints
For PHP seems to not be a good solution since is not provided by the Google's Cloud documentation, as you can see here.
Nonetheless, there are some documentation regarding how you can use PHP within Cloud Endpoints via the JWT's client, as you can see here, and also here.
If neither of those fit your needs you can always use a custom method to authenticate users. As you know to authenticate a user, a client application must send a JSON Web Token (JWT) in the authorization header of the HTTP request to your backend API.
As a consequent, you could use the Extensible Service Proxy (ESP):
The Extensible Service Proxy (ESP) validates the token on behalf of your API, so you don't have to add any code in your API to process the authentication. However, you do need to configure your OpenAPI document to support your chosen authentication methods.
You could see how to implement custom method authentication for users here..
Finally, in case you are interested I link some other authentication methods that you could use with your Cloud Endpoints services in case none of the above fit your needs.
I hope it helps.

Related

Decoding Keycloak JWT Token

I'm trying to validate (and read roles from) a JWT Token. Sadly I can't use any adapter or auto configuration due to my overall application architecture.
It's no problem to decode the token like any other JWT Token, but I wonder if there is a library from Keycloak to archive this goal. (For example Just Parse the token to something like a KeycloakJWTToken and verify it by grabbing the secret from Keycloak Server or so)
Any easy-to-use client or so?
I'm using the Jose4J library:
https://bitbucket.org/b_c/jose4j/wiki/Home
Reading the claims inside a JWT token is straightforward:
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
public void parseJWT(String token) throws Exception {
JwtConsumer consumer = new JwtConsumerBuilder()
.setSkipAllValidators()
.setDisableRequireSignature()
.setSkipSignatureVerification()
.build();
JwtClaims claims = consumer.processToClaims(token);
System.out.println("* Parsed token: "+ claims.getRawJson() );
System.out.println("* Expiration date: " + new Date(claims.getExpirationTime().getValueInMillis()) );
}
More examples are available on GitHub:
https://github.com/pvliesdonk/jose4j/blob/master/src/test/java/org/jose4j/examples/ExamplesTest.java
Last remark: you do not need a key nor a secret to parse the JWT, but if needed, you can use the server (public) key to verify the token was signed by the keycloak server you are trusting.
The JWT website is listing all libraries for Token Signing/Verification:
https://jwt.io/#libraries-io
Keycloak access tokens are indeed JWT tokens. So, you can make full use of existing JWT libraries, including for validation as stated in the Keycloak official documentation:
If you need to manually validate access tokens issued by Keycloak you can invoke the Introspection Endpoint. The downside to this approach is that you have to make a network invocation to the Keycloak server. This can be slow and possibily overload the server if you have too many validation requests going on at the same time. Keycloak issued access tokens are JSON Web Tokens (JWT) digitally signed and encoded using JSON Web Signature (JWS). Because they are encoded in this way, this allows you to locally validate access tokens using the public key of the issuing realm. You can either hard code the realm’s public key in your validation code, or lookup and cache the public key using the certificate endpoint with the Key ID (KID) embedded within the JWS. Depending what language you code in, there are a multitude of third party libraries out there that can help you with JWS validation.
Besides, in Java EE, using the Keycloak Java adapter, the roles are typically mapped on the user Principal and i.e. allows isUserInRole(). That's one of the goals.
Also it is possible to cast the Principal from the SecurityContext as a KeycloakPrincipal, then obtain in turn a KeycloakSecurityContext from it. Using the KeycloakSecurityContext you have access to both ID and Access tokens (when applicable) and can read their properties, attributes and claims.
Note that it is also good practice, and simply useful, to use the Keycloak UI to "evaluate" your tokens. For instance, you can see the generated token in the Client Scopes tab (under Evaluate), as well as evaluate your policies and permissions in the Authorization tab of your Client(s) (under Evaluate).
Cf. https://www.keycloak.org/docs/latest/server_admin/#_client_scopes_evaluate
That's probably the best way to debug and test, while setting up your Client(s).
If you select a user in the Evaluate screen, the following example data is generated:
Generated Access Token (...)
Generated ID Token (...)
Generated User Info (...)
All examples are generated for the particular user and issued for the particular client, with the specified value of scope parameter. The examples include all of the claims and role mappings used.
Source: https://www.keycloak.org/docs/latest/server_admin/#generating-example-tokens-and-user-info

registering a rest API with OAuth

I have written a web application which makes REST API calls to a message broker. The message broker contains already written REST APIs to which can be used to get message broker data. The message broker is written in a way in which each REST API call sends the user name and password which is encoded with base64. I need to make a login to my web app and authenticate it with OAuth.Does anyone know how to do this? How to authenticate the REST APIs with OAuth?
Step 1: Add OAuth 2.0 to your web server. This is very standard with lots of libraries available. You did not specify the Identity Provider that you will use (Google, Facebook, Auth0, Okta, etc), but each vendor has documents and libraries for you to use in your desired language.
Step 2: Add an Authorization Header to your API calls. The standard method is to add the HTTP header Authorization: Bearer access_token when making an API call.
Step 3: Add OAuth token verification to your API. When your API receives a request, it extracts the Authorization header and verifies the Bearer token. How this is done depends on the Identity Provider. For example, some vendors provide a Signed JWT (which you verify with the vendors public certificate), others provide an opaque access token (which you verify by calling the vendor's token endpoint). Add internal caching of tokens so that you don't need to verify on every API call.
If you understand OAuth 2.0 the above steps are straightforward to implement. If you don't Oracle has a set of videos which are excellent for getting started understanding OAuth.
Oracle Cloud Primers
If your desired OAuth implementation does not require users logging in and is a server to server service that you control on both ends, then you can use just part of OAuth which is Signed JWT (JWS). You create a Json data structure with your desired content and sign it with a private key. This creates a token that you can use in the above steps. You would then validate the token using your public key. You can use self-generated keypairs generated by OpenSSL or similar products for your signing and verification.

Serverless Framework with server-side authentication and Cognito

I have already implemented various REST-APIs using the Serverless Framework with APIG, DynamoDB as data storage and Cognito for user authentication with Angular2 as frontend. The functions can easily be secured by a Cognito authorizer on the server-side. The downside is that I have to integrate AWS SDK in my frontend applications in order to authenticate the user with Cognito first (signup/signin, ...). I could also use the AWS_IAM authorizer but then I also have to sign all requests on the client side with an AWS specific signature before sending the request to the API Gateway.
Now I was wondering if there is any possibility to keep authentication and authorization on the server side, so I can use an open standard like JSON Web Tokens for signup/signin? This would allow me to open my REST-API for other developers as well without forcing them to use Cognito at all.
I know that one possibility would be to implement a custom authorizer for my lambda functions but isn't there anything stable, which can be used "out-of-the-box" already? Most of the examples I found are using Cognito or IAM auth AWS signature signin on client side (e.g. serverless-stack.com).
It is curious that I didn't find any useful informations about this on the web so far, since I think that this is a typical use case for REST APIs. Or do I have a conceptual misunderstanding about API Gateway + Cognito?
I have been through the same trouble in understanding the way how AWS Cognito works and what options are available to implement authentication & authorization. Unfortunately there is no out-of-the-box method available to do it for your requirement. Nevertheless let's hope that Amazon comes up with a feature very soon.
Basically, there are 3 options available to implement authentication.
AWS_IAM
Cognito Authorizer
Custom Authorizer
AWS_IAM
In addition to authentication, this method can be used to implement authorization using IAM Roles or IAM Users easily. The only downside of it is that you need to send a request signed with an aws-signature-4 which is not the standard way that we have seen in IDP services like Auth0.
Cognito Authorizer
This method meets the expectation of sending a JWT token with API requests. You can create users in Cognito User Pool and then use it to authenticate and generate an IdToken. However, this method will only allow you to authenticate users; authorization needs to be handled in method level.
Custom Authorizer
This method can be used to write your own way of authentication and authorization. Also it helps to eliminate writing authorization logic in API methods. The ideal solution would be to use AWS Cognito User Pool to authenticate users and then generate a policy document for IAM Role to access resources.
Here is an example AWS cognito userpools JavaScript SDK get user's policy documents.
Also keep in mind that this solution will be invoking an extra lambda function for each request that you make.
You can use Cognito Auth to Server-side. Following would be the steps.
Implementing Sign-up and Sign-in
Implement Sign-up form in the frontend and API Gateway endpoint(e.g /register) using Lambda to receive, the Sign-up data, which will create user in Cognito using AWS SDK. For detailed reference check this link.
AWSCognito.config.region = 'us-east-1'; //This is required to derive the endpoint
var poolData = { UserPoolId : 'us-east-1_TcoKGbf7n',
ClientId : '4pe2usejqcdmhi0a25jp4b5sh3'
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var attributeList = [];
var dataEmail = {
Name : 'email',
Value : 'email#mydomain.com'
};
var dataPhoneNumber = {
Name : 'phone_number',
Value : '+15555555555'
};
var attributeEmail = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataEmail);
var attributePhoneNumber = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataPhoneNumber);
attributeList.push(attributeEmail);
attributeList.push(attributePhoneNumber);
userPool.signUp('username', 'password', attributeList, null, function(err, result){
if (err) {
alert(err);
return;
}
cognitoUser = result.user;
console.log('user name is ' + cognitoUser.getUsername());
});
Do similarly for the Sign-in by creating an frontend & API Gateway endpoint(e.g /login)
var authenticationData = {
Username : 'username',
Password : 'password'
};
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
var poolData = { UserPoolId : 'us-east-1_TcoKGbf7n',
ClientId : '4pe2usejqcdmhi0a25jp4b5sh3'
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var userData = {
Username : 'username',
Pool : userPool
};
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
console.log('access token + ' + result.getAccessToken().getJwtToken());
/* Use the idToken for Logins Map when Federating User Pools with Cognito Identity or when passing through an Authorization Header to an API Gateway Authorizer */
console.log('idToken + ' + result.idToken.jwtToken);
},
onFailure: function(err) {
alert(err);
},
});
Storing and sending the JWT from your Browser and Validating at API Gateway.
After receiving the JWT from the Sign-in API endpoint, you can store it locally in user's browser, using HTML5 Localstorage, Sessionstorage or Client Side Cookie. Optionally if you need to use Server Side Cookies, it will require to have a Proxy backend which keeps the Session state with the Web App and Convert it to the JWT to invoke the API Gateway.
From the Web Browser(Assuming your client directly invokes API Gateway) set a HTTP header called Authorization and forward the JWT to the API Gateway invocations.
At API Gateway use Cognito Authorizer to as the Authorize the token where it will also forward the user identity resolved to your Lambdas.
Note: Here I have purposefully avoided the IAM Authorization since it will require some additional work from Web App JavaScripts to implement Signature 4 Signing at Browser and also requires to refresh the token frequently which is straightforward with AWS JavaScript SDKs but will become complex if you need to implement it on your own.
Please take a look at this here.
The example demonstrates various configurations that include custom authorizers, cognito, lambda, dynamoDB etc.

Programatically create an OpenID Connect id_token with IdentityServer3

I am adding IdentityServer3 on to an existing website (NopCommerce to be specific). It has it's own registration and authentication system, but we need to also offer OpenID Connect so that a back end application can be integrated. Calls to the back end need to have an id_token for the current user that the back end validates to confirm the identity.
I've found information about how to use an existing membership database to provide the user data for IdentityServer3 to check, however I am bit stuck on how to generate the id_token for each user. I guess the obvious answer is to replace the website login with IdentityServer, however that raises further issues for the rest of the project. Ideally I'd like the user to log in as normal and then call a method in IdentityServer to generate the id_token.
Is this possible? I've been hunting around, but can't find anything so far. The best I found was an answer to programmatically sign in to identityserver3. I think it's suggesting making a HTTP post to IdentityServer, but it feels kind of hacky.
I also found Implementing OAuth 2.0 and OpenId Connect provider using IdentityServer3 with existing login server and membership provider, but I have to admit it's assuming quite a bit of knowledge I don't have (yet).
My solution based on John C's answer worked using a NopCommece external authentication plugin, but I was unhappy with having to leave Nop to authenticate and register when IdentityServer was using the Nop database. Going via the external auth route seemed to be the only way to get an OpenID Connect id_token. After a break and some time to revisit the code though I found the following:
https://identityserver.github.io/Documentation/docsv2/configuration/serviceFactory.html
https://identityserver.github.io/Documentation/docsv2/configuration/serviceFactory.html
By implementing custom services, IdentityServer allows you to mess with the token creation and generation AND the dependency injection system it uses gives you access to instatiated versions of the default services.
Previously I had followed an answer which sent a username and password to the token endpoint. The OpenID specs say that this should only return the access_token, which is exactly what DefaultTokenService in IdenttyService does. By adding a CustomTokenResponseGenerator however, I was able to re-use the request to create and return an id_token too.
CustomTokenResponse class:
internal class CustomTokenResponseGenerator : ICustomTokenResponseGenerator
{
protected ITokenService _tokenService;
public CustomTokenResponseGenerator(ITokenService tokenService)
{
_tokenService = tokenService;
}
public Task<TokenResponse> GenerateAsync(ValidatedTokenRequest request, TokenResponse response)
{
var tokenRequest = new TokenCreationRequest
{
Subject = request.Subject,
Client = request.Client,
Scopes = request.ValidatedScopes.GrantedScopes,
//Nonce = request.AuthorizationCode.Nonce,
ValidatedRequest = request
};
var idToken = _tokenService.CreateIdentityTokenAsync(tokenRequest);
idToken.Wait();
var jwt = _tokenService.CreateSecurityTokenAsync(idToken.Result);
response.IdentityToken = jwt.Result;
return Task.FromResult(response);
}
}
How to inject the custom service in Startup.cs:
factory.TokenService = new Registration<ITokenService, TokenService>();
factory.CustomTokenResponseGenerator = new Registration<ICustomTokenResponseGenerator, CustomTokenResponseGenerator>();
When user logs-in into NopCommerce application, you can send an HTTP authorize request to identityserver. Make sure while sending the authorize request to idsrv you are using prompt=none, this way you will get the id_token or access_token without showing a consent to the user again if the user is already logged-in.
function getAuthorizeRequest() {
var url = global.appSettings.identityServerURL
+ "/connect/authorize?client_id=siteB&response_type=id_token token&redirect_uri="
+ global.appSettings.siteBUrl + "/Main/NopCommerceapp&scope=siteBscope openid email roles&prompt=none&nonce="76767xz676xzc76xz7c67x6c76"
return encodeURI(url);}
Checkout idsrv authorize endpoint https://identityserver.github.io/Documentation/docsv2/endpoints/authorization.html
I think your best solution would be to implement IdentityServer3 and get it reading from your existing Nop membership database. Then create a Web API app that runs on its own that utilizes your IdentityServer3 setup. Inside the Web API, you implement all the functionality that your back end app needs, reading and writing to the Nop database.
Keep your Nop frontend UI separate from your backend API. If you follow the two links below, you should be able to get something up and running pretty quickly.
Creating the simplest OAuth2 Authorization Server, Client and API
MVC Authentication & Web APIs

OAuth2RestTemplate with prefetched JWT token

JWT OAuth2 Token is prefetched from Spring Auth Server and stored in Redis Storage.
I don't want to request access token in OAuth2RestTemplate and I want to use my JWT Token for requests.
Can I do it with OAuth2RestTemplate or I should use usual RestTemplate?
The documentation for spring-security-oauth is useful here, basically the two sections: JWT Tokens and Accessing Protected Resources:
JWT Tokens
To use JWT tokens you need a JwtTokenStore in your Authorization
Server. The Resource Server also needs to be able to decode the tokens
so the JwtTokenStore has a dependency on a JwtAccessTokenConverter,
and the same implementation is needed by both the Authorization Server
and the Resource Server. The tokens are signed by default, and the
Resource Server also has to be able to verify the signature, so it
either needs the same symmetric (signing) key as the Authorization
Server (shared secret, or symmetric key), or it needs the public key
(verifier key) that matches the private key (signing key) in the
Authorization Server (public-private or asymmetric key). The public
key (if available) is exposed by the Authorization Server on the
/oauth/token_key endpoint, which is secure by default with access rule
"denyAll()". You can open it up by injecting a standard SpEL
expression into the AuthorizationServerSecurityConfigurer (e.g.
"permitAll()" is probably adequate since it is a public key).
To use the JwtTokenStore you need "spring-security-jwt" on your
classpath (you can find it in the same github repository as Spring
OAuth but with a different release cycle).
Accessing Protected Resources
Once you've supplied all the configuration for the resources, you can
now access those resources. The suggested method for accessing those
resources is by using the RestTemplate introduced in Spring 3. OAuth
for Spring Security has provided an extension of RestTemplate that
only needs to be supplied an instance of
OAuth2ProtectedResourceDetails.
This basically means to me that you'll use the same spring-security-jwt JwtAccessTokenConverter class in both the authorization server and the resource server and that the token services in each need to be setup with the JwtTokenStore(). The extension to the RestTemplate class they're referring to is the OAuth2RestTemplate from spring-security-oauth2. You'd use it in your resource server with it's JWT smarts being provided by an equivalent token recognizer.
Because the spring-security-oauth2 code is already set up to handle JWT tokens, you just need to provide a few key pieces and let the framework do the heavy lifting of inspecting the token and putting the security into scope for each protected resource.
As it would happen, someone's posted a nice example of this which goes into detail: baeldung spring-security-oauth-jwt example and here: github project of the same including how one could provide a more customized JWT (claims/payload).