How to securely generate a session token that can be independently verified by Auth instances - authentication

I'm currently working on making an authentication gRPC microservice using Rust and Tonic. The simple idea is that my service generates a token that can later be used to reference back to the UserID. I save this token and user relationship in a redis database so I can run multiple of these authentication services in tandem. I'm currently generating my tokens like this:
// Create a session for a username
pub fn create_session_id(username: &String) -> String {
// Generate unique ID
let id = Uuid::new_v4();
// Hash the ID and username for a unique session token
let mut hasher = Sha256::new();
hasher.update(id.to_string() + username);
// Return hexadecimal string encoding of hash
format!("{:X}", hasher.finalize())
}
I will be the first to admit it's a bit primitive. My problem is that there's nothing stopping a potential attacker with access to this database from inserting their own arbitrary token with an associated userid. This means I will have to be able to verify my token came from my authentication service. How do I generate a session token that can be independantly verified by any one of my auth instances without making it vunerable to forgery.
I have thought about implementing OAuth2, but I'm struggling to integrate that with the gRPC microservice architecture.
Any help would be appriciated.

Related

Can "context" from HTTPS callable Cloud Functions be trusted?

I am using Cloud Functions to handle read/write to Cloud Firestore on the server side. The Cloud Functions are triggered by clients in the web app using HTTPS callable function.
When calling a Cloud Functions using HTTPS, there is a parameter sent from the client call "context" that carries user auth information. For example, a Cloud Functions on the server can look like this:
// Saves a message to the Firebase Realtime Database but sanitizes the text by removing swearwords.
exports.addMessage = functions.https.onCall((data, context) => {
// ...
});
However, since context is passed by the client, and the client could pass in a manipulated ID token, do I need to always perform a ID token verification before trusting and using something like context.auth.uid to interact with my database?
The ID token verification I am talking about is this:
// idToken comes from the client app
admin.auth().verifyIdToken(idToken)
.then(function(decodedToken) {
var uid = decodedToken.uid;
// ...
}).catch(function(error) {
// Handle error
});
Essentially, I want to know if Firebase performs ID token verification automatically when passing context using https call and therefore I can go ahead and trust that if the client has manipulated context, the https call will fail due to token verification failing. Or, do I need to explicitly do a manual ID token verification on the server every single time to check the integrity of context, since the client can easily insert a manipulated token using the browser's devtools or something like that.
Yes, the ID token is automatically included in the request and verified in the function. You don't have to write code to verify the toekn when using callable functions.

Better way to implement authentication in microservice architecture using vert.x

Someone have idea how to implement authentication and autorization process in vert.x microservice architecture thru API Gateway service and standalone user service, where it has own custom Auth provider? Should it use shared data (hazelcast map) to store some user information like name, roles by token or something else? I,m breaking mind..
As part of a microservices architecture, I'd not implement the authentication directly in my vert.x microservice but I'd go through with an API management gateway like tyk or kong for example.
Then I'd only check the permissions of the user over the data in my microservice using any database you want.
You can also dig this track if you really want to handle authentication directly in your microservice.
Having a user service, I wanted all authentication and authorization operations to be performed through it.
In the end, I did this:
jdbcAuth.rxAuthenticate(authInfo)
.map(user -> user.principal().getString("username"))
.flatMap(username -> roleRepository.findByUsername(username).map(roles -> {
JWTOptions jwtOptions = new JWTOptions().setAlgorithm("RS256");
roles.forEach(jwtOptions::addPermission);
LOGGER.info("Token successfully created");
String token = jwtAuth.generateToken(new JsonObject().put("username", username), jwtOptions);
return new JsonObject().put("accessToken", token).put("tokenType", "Bearer");
}))
.subscribe(SingleHelper.toObserver(handler));
For user authentication I use JDBCAuth (and solt hash generation for new user creation)
If there is such user we are getting roles, generate a token with optional claims like "username" and JWTOptions with perrmissions.
Putting into request header Authorization: Bearer --token--
On other microservices we put global JWTAuth handler with pulicKey like:
JWTAuthHandler.create(JWTAuth.create(vertx.getDelegate(), new JWTAuthOptions().addPubSecKey(new PubSecKeyOptions()
.setAlgorithm("RS256")
.setPublicKey(<PUBLIC_KEY>))));
This handler sets the user to the context, and we can get it through context.user () and check the permissions. By the way, we can put this handler along with the addAuthority() method on the route for access checking.

Enabling OAuth1 Support on a Jersey Jax-rs web service

I'd like to enable OAuth1 Provider support on my restful web service. Jersey supports this as described here Jersey OAuth1 Provider support.
I've been trying to register it as so:
public ApplicationConfig(){
super();
addRestResourceClasses(getMyResourceClasses());
register(new OAuth1ServerFeature(new DefaultOAuth1Provider(),"/oauth/access_token","/oauth/request_token"));
}
But, when I register the OAuth1ServerFeature, I get a 404 when trying to access my resources.
Can't seem to find any examples/tutorials implementing jersey oauth support anywhere!
Is there a simple component I can plug into my jax-rs service to enable oauth support?
I realise this thread is somewhat old - but having just got it work myself, I felt a reply was in order! Given time, I may even create a blog post with a fuller example. Be warned - this is not a short answer!
There is an absolute lack of examples on information on using the OAuth1 server (aka Provider) feature in Jersey - I can't remember a tech topic that revealed so little useful Google information. I almost passed on looking for another solution since it led me to think perhaps it didn't work. But, with some perseverance, I can say that not only is it usable, but it seems to work rather well. Plus of course, if you're already using Jersey for your REST API - you don't need any extra libs.
I am not an OAuth1 expert - and I'd strongly recommend some background reading for those attempting this. I am also assuming here you have Jersey working, understand things like ContainerRequestFilters, and also have some internal means to authorize users.
My examples also use the excellent JAX-RS OSGi connector - the only real difference is that where we use an OSGi bundle context to register the OAuth1 feature via an OSGI service, regular Jersey users will need to configure via their normal Application / Server config model.
Initialisation
You must create your OAuth1 feature - and give it a provider:
DefaultOAuth1Provider oap = new DefaultOAuth1Provider();
Feature oaFeature = new OAuth1ServerFeature(oap, "oauth1/request_token", "oauth1/access_token");
Don't forget to register oaFeature into Jersey!
The DefaultOAuth1Provider is entirely memory based - which was fine for us to start with. Many will want to persist access tokens for use across server restarts, which will require an extended subclass (or clean implementation)
Add in your Consumers Keys and Secrets
It took me a while to realise Consumers were not users but clients i.e. applications. The Jersey implementation will not work if you don't register keys and secrets for each consumer (aka client app) that wishes to connect
oap.registerConsumer("some-owner-id",
"abcdef" ,
"123456",
new MultivaluedHashMap<String,String> ());
You obviously would never hard-code these, and further would use some form of secure store for the secret (param 3).
If you do not add these you will not get any further.
OAuth protocol step 1 - get a request token
At this stage you are ready client side to get a request token - and here there is a perfectly good example on GitHub.
ConsumerCredentials consumerCredentials = new ConsumerCredentials("abcdef","123456");
//TODO - user proper client builder with real location + any ssl context
OAuth1AuthorizationFlow authFlow = OAuth1ClientSupport.builder(consumerCredentials)
.authorizationFlow(
"http://myhost:8080/myapi/oauth1/request_token",
"http://myhost:8080/myapi/oauth1/access_token",
"http://myhost:8080/myapi/oauth1/authorize")
.build();
String authorizationUri = authFlow.start();
System.out.println("Auth URI: " + authorizationUri);
Obviously you would change URLs to point to your server and - crucially - the client needs to use the same Conumer Key and Secret you registered in the server.
You will get back a response with an oauth_token string in it e.g.
http://myhost:8080/myapi/oauth/authorize?oauth_token=a1ec37598da
b47f6b9d770b1b23a5f99
OAuth protocol step 2 - authorize the user
As you will read in any article, actual user Authorization is outside of the scope of OAuth1 - at this stage you must invoke your servers auth process whatever that is.
However!!!! What is not outside the OAuth1 scope is what your server needs to do if the user authorizes successfully. You must tell your DefaultOAuth1Provider about the successful auth:
// Dummy code - make out like we're auth'd
Set<String> dummyRoles = new HashSet<> (Arrays.asList( new String[] { "my-role-1", "my-role-2" }));
DefaultOAuth1Provider.Token tok1 = getRequestToken("a1ec37598da
b47f6b9d770b1b23a5f99");
String verifier = authorizeToken(tok1, new Principal()
{
public String getName()
{
return "my-user";
}
},
dummyRoles);
System.out.println("***** verifier: " + verifier);
Note the request token string is that from step 1. Obviously a real implementation would pass a real Principal and set of roles for the authorized user.
Also, of course, printing out the verifier is not much use - you need to get that back to your client in some way, either via an independent channel or possibly as a header in the auth response - which maybe would need to be encrypted for added protection.
OAuth protocol step 3 - swap the request token for an access token
Once the client receives or has the verifier entered manually, it can finalize the process and swap the request token for an access token e.g.
String verifier = System.console().readLine("%s", "Verifier: ");
final AccessToken accessToken = authFlow.finish(verifier);
System.out.println("Access token: " + accessToken.getToken());
Again, not a realistic example - but it shows the process.
If your OAuth1Provider saves access tokens to some persistent store on the server, you can re-use any access token returned here on a future session without going through all the previous steps.
That's it - you then just need to make sure every request the client creates from this point on in the process makes use of that access token.

How to get Authorization Token

I secured my Web Api using Token Based authentication. All works well, but for now before making an api call, I request for a token by making separate api call which will return me the token for making further request. What I am wondering is there any possible way that I can generate token on client side which will be decrypted on the server?
OR
What you think, I am on the right track?
Here is my jQuery Code
$.when($.get("/api/service/GetToken"))
.done(function (token) {
doAjaxCall("GET", "/api/service/GetAllJobsStatusCount/1/admin", "{}", "json", token, function (data) {
console.log(data);
});
});
Here is my method which will return me token
[Api.HttpGet]
public string GetToken()
{
var authorizeToken = "apikey";
return Rsa.Encrypt(authorizeToken);
}
Please suggest
A single token only works for authentication if an encrypted connection (HTTPS) is used - otherwise, MITMs can read the token and steal the identity. If everything is done using secure connections, it doesn't matter who calculates the token, as long as it is exchanged before any authentications, so both partners know it beforehand - otherwise there would be no way to know if it's valid or not. Note however that the token can always only prove that the client is the one that the token was given to (or recevied from) in the first place, you still don't know anything else (for example if the other person was who he claimed when te exchange was made).
If not using secure connections, I'd suggest using public-key encryption. If not encrypting the whole request, calculate a signature and sign it with the private key clientside, verify it server-side. In this case, the client MUST calculate the private and the public key and hand the public key over to the server, as the server should never know the client's private key (and it shouldn't ever be sent over a unencrypted connection either, after all that'S the whole point of using PKI).
For another approach (that is widely used, but not extraordinary secure), see OAuth.
[Edit]: Addition based on comment:
To verify a client, every request that accesses valuable data has to be authenticated. That means: the client needs to send something that is able to prove that it is who it claims to be along with EVERY request (as HTTP is a stateless protocol).
The usual way is to exchange some secret once, that is valid for either a limited time or forever, and only known to the client and the servet. That way, the server can verify idientities by checking if the client sent the token it was given. Expiring tokens after improves security, but when a client requests a knew one, there is no way to tell if it is the same client that used the old one (unless the request is validated by the old token and that one is still valid).
If ther client calculates the token, that deosn'T change anything - it sends it once and tells the server who it is, then every request that carries the same token does most likely come from the same client. There is only one additional thing the server has to do here: If two clients calculate the same token, the server has to reject the token from the second client and request another one. Otherwise, clients cannot be distinguished anymore.

How to determine user is authenticated in WCF service

i am new in wcf so one question bugging me like wcf and user authentication. generally in asp.net i send user name and password and at the server end it is validated against database and if user is valid then i store some data in session and in every page i check the session and if the session exist and true is stored for that user in that session then i let the page execute otherwise i redirect user to login page. so i want to know how to implement this kind of user authentication in wcf. i want when first time user will call any method of my service then he will pass credential and if credential is fine then he can call any method of my service. please guide me how could i do it in wcf. in wcf how i can store any data in session for each user who will call my service....is there any way??
i search google and found one like http://blog.adnanmasood.com/2010/04/29/step-by-step-guide-for-authenticating-wcf-service-with-username-and-password-over-ssl/
but here anyone notice caller pass user name & password but code look like user name and password comes twice like
private static void Main(string[] args)
{
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(
delegate { return true; });
var client = new WcfServiceClient();
GetCredentials();
client.ClientCredentials.UserName.UserName = username;
client.ClientCredentials.UserName.Password = password;
Console.Write(client.GetData(1));
client.Close();
Console.Read();
}
...but why two user name and password is coming UserName.UserName it looks very ugly.
give me the best idea how to authenticate users against DB when they first time call my service and once authenticated then from the next time he can call any method of my service without giving credentials.
some one told me to develop service for authenticate user.once user authenticate then service will provide some unique token id to each wcf client and client will pass that token as message header when call any method......i have no idea how to implement it and even i do not know would it be best or not. so looking for guidance and suggestion. thanks
The most common way of dealing with WCF authentication is to have the client program ask for username and password once (or retrieve it from a config file), and have the client program provide it for every service call. Some examples can be found at http://msdn.microsoft.com/en-us/library/ff405740.aspx.
The alternative is to have user sessions, which are generally a bad idea. Sessions do not scale easily, there are client and server platform compatibility considerations etc...