How can I implement Dropbox OAuth2 + PKCE flow with Blazor Webassembly? - oauth-2.0

I am trying to use the Dropbox.Api dotnet SDK, which is built on netstandard 2.0, by translating the example from the docs here into a Blazor Webassembly project. I have narrowed down the issue to the fact that the PKCEOAuthFlow class uses private members CodeVerifier and CodeChallenge to implement the PKCE flow, and these private members are generated and set only in the constructor, which makes sense.
So here is specifically where I am stuck: How can I persist that exact object with its one-time generated CodeVerifier/CodeChallenge which must be the same when I try to call ProcessCodeFlowAsync after the Dropbox redirect back to my app?
I have tried the following:
Opening the dropbox authorize URL in a new tab so that the main tab stays open. This fails because when Dropbox redirects the user back, they stay in the new tab and my object is only still alive back in the first tab.
Making an ILoginService class, injecting it into my pages as a singleton by doing builder.Services.AddSingleton<ILoginService, DropboxLoginService>(); inside Program.cs, but I always get a new one. I am not sure exactly why this fails, but I believe that the entire Webassembly app goes out of scope when I send the user to Dropbox and after the redirect it has to create a new ILoginService anyways.
I also tried making my entire DropboxLoginService class static, with a static PKCEOAuthFlow member set in the static constructor. I also end up with a new object every time when I do it this way, probably for the same reason as #2.
I tried saving my object to the browser session storage using Blazored.SessionStorage, but I quickly realized this does not persist any private members, and the object that I retrieve after the redirect again has a new CodeVerifier and CodeChallenge.
DID NOT TRY THIS YET - I think that MAYBE I could serialize the entire object in some binary format, then save a base64 string to the session storage to retrieve it later. However, this feels like a security hole considering that the whole point of PKCE is to avoid untrustworthy storage with sensitive information. It would basically negate the security since an intrepid hacker could possibly get at that object and MITM my user somehow. Basically it is no more secure than going back to normal OAuth2 with my app secret stored somewhere.
Am I making this too complicated? Is there some way to keep my PKCEOAuthFlow object in memory from the start to the end of my flow, across the 2 redirects from my app -> Dropbox -> back to my app? I think this question goes beyond Dropbox and would apply to any OAuth2 + PKCE flow implementation in Blazor Webassembly, or really any serverless SPA or PWA.

Related

Is it possible to use recaptcha with auth0 in some way to avoid having a user to sign in but still have a token?

I have an app, client side, that uses auth0 for accessing the different API's on the server. But now I want to add another app, a single page app, I'm going to use VueJs, and this app would be open "ideally" w/o a user having to sign in, it's like a demo with reduced functionality, I just want to check that the user is not a robot basically, so I don't expose my API in those cases.
My ideas so far:
- Somehow use recaptcha and auth0 altogether.
- Then have a new server that would validate that the calls are made only to allowed endpoints (this is not of my interest in the question), so that even if somehow the auth is vulnerated it doesn't leave the real server open to all type of calls.
- Pass the call to the server along with the bearer token, just as if I was doing it with my other old client app.
Is this viable? Now I'm forcing the user to validate, this is more a thing about UX (User-experience), but I'd like a way to avoid that. I'm aware that just with auth0 I can't do this see this post from Auth0, so I was expecting a mix between what I mentioned.
EDIT:
I'm sticking to validating in both cases, but I'm still interested to get opinions over this as future references.
At the end, with the very concept of how auth0 works that idea is not possible, so my approach was the following:
Give a temporary authenticated (auth 0) visitor a token which has restricted access level, then pass the request to a new middle server, the idea is to encrypt the real ids so the frontend thinks it's requesting project A123456etc, when indeed it's going to get decrypted in the middle server to project 456y-etc and given a whitelist it will decide to pass the request along with the token to the final server, the final server has measures to reduce xss and Ddos threats.
Anyway, if there's a better resolve to it I will change the accepted answer.
You could do a mix of using recaptcha for the open public, then on the server side analyse the incoming user request (you can already try to get a human made digital fingerprint just to differentiate with a robot-generated one) and the server (more a middle server) makes the call to you API (and this server has limited surface access)
What we normally do in these situations (if I got your issue correctly) is to create two different endpoints, one working with the token and another one receiving the Recaptcha token and validating it with Google servers.
Both endpoints end up calling the same code but this way you can add extra functionality in a layer in the 'public' endpoint to ensure that you are asking only for public features (if that cannot be granted just modifying the interface).

Using a Custom Single Sign On Authentication Service with Spring Security Core Plugin

I'm working on a Grails application and want to integrate with a custom single-sign-on service (not CAS, but similar). I'm struggling to find all the pieces that I need to customize to make this happen. Can someone explain to me a general outline as to what I need to use to accomplish this? I've read the documentation on the plugin, but it assumes I know which beans to override and where to put all the needed files.
I've block-quoted what I think needs to be done based on my research below each point.
Order of Operations
1- The user requests secure content (everything is secure in the application for now)
I believe this setting is in the Config.groovy file:
grails.plugins.springsecurity.rejectIfNoRule = true
grails.plugins.springsecurity.securityConfigType = "InterceptUrlMap"
grails.plugins.springsecurity.interceptUrlMap = [
'/**':['ROLE_ADMIN']
]
2- Spring Security checks to see if the user has a specific value set in a cookie provided by the authentication service
I'm guessing I need to create an authentication filter, but I don't know where to put it or what it should look like.
If they don't, the user is redirected to this custom SSO service, they login, once authenticated, the user is redirected back to my application (with a new cookie set)
3- Spring security checks for the cookie value and validates it against the custom service (via HTTP POST)
From some research, I think that I need to use PreAuthenticatedProcessingFilter, but I haven't been able to find any examples of how to do this.
4- The custom service returns a series of name/value pairs, a user then needs to be created in the local application database (or the timestamp of "lastLoggedIn" is updated if they user's data is already in the database)
I believe this is done in the same PreAuthenticatedProcessingFilter as number 3 or in a GrailsUserDetailsService
5- The user's authentication is cached in the session for a period of time (6-8 hours) so that re-validation against the SSO service doesn't need to occur every time the user requests a new resource.
I'm not sure if this is something that's done inherently or if I need to add code to do this (and also set the session timeout)

HttpSession without cookie

I have an application a the moment which for a particular set of reasons will be interacting oddly with the hosting server.
The application is to be accessed through a larger portal and can be encapsulated within the portal display, however it makes extensive use of AJAX requests which are not intercepted by the portal. These requests are made directly to the hosting server, however I am seeing a problem.
When the first ajax request is made (a little way into the application flow) the Ajax request is not carrying with it the JSessionId cookie (obviously as it's sending this to a different server than it received it from)
Is there a good grails way to find the session the AJAX call should be interacting with. I have tried setting grails.views.enable.jsessionid to true, but this only works if the browser is not accepting cookies.
Create a hidden form input value that has the jsessionid in it on the page you send back to the portal on the first request. Then read that form variable, and set the cookie in your javascript code that makes the AJAX request.
I'm guessing seeing that this already works, cross-site scripting isn't an issue? AJAX requests to domains other than that which the main page originated from will be blocked by the browser.
The most reliable way will be for you to set up your own "cookie" and pass that along with the requests.
It sounds like you are running into issues due to the portal and it's cookies and then having to continue that "session" onto a different server. Your application needs to simply handle it's own sessions itself in order to prevent getting stomped on by the "normal" cookies.
The idea is essentially to create a session token when the portal makes a request from to your application, and then the subsequent AJAX calls your application makes back to it's own server should include that token. You can then easily associate that token with the session you need to be using.
If you are looking to make it a bit more robust and handle it above the level of your application, you can leverage the fact that Grails is built on Spring MVC deep down and override the default session handler to pick up on whatever mechanism you decide to go with. I'm not sure of exactly how to do this with Grails, but I've done similar things on Spring MVC projects and it isn't too tough once you get your head wrapped around the various injection points of the framework.
It isn't ideal, since there is now a fair bit more complexity, but in theory, the benefits of the portal are outweighing the added complexity required for traditionally "handled" things like sessions and expiring them, etc.

How to authenticate from a token in a URL?

I need to create a website with non standard authorizaion logic (or rather not exactly the site. It should be separate Area in existing ASP.NET MVC3 application). Access to most of the pages sould be available only to authorized users. Authorization is carried out on the token passed in the link. After the user arrived to this area, the token should be checked and if it’s valid site will create a session key for 30 minutes (we already have our own mechanisms of session managment and it should be used).
Workflow example :
Third-party website generates a link for user, e.g. https://example.com/securedPage/?accountId=123456&token=XXXXX
Our site check this token (it depends on the page from URL, in this case https://example.com/securedPage/)
If the token is valid, example.com obtains a session key for the user and stores it in cookies.
Then user continues browsing whole website and only session is checked.
I’m new to MVC framework, so I’d like to ask several questions about architecture.
What is an apropriate place for this logic? ActionInvoker, Global.asax etc.?
Currently I'm trying to create my own ActionInvoker and keep this logic there, but I'm afraid that it could be a wrong way.
If I understand correctly you want yo extend the Action of the controller to inject/check your token.
I think the global action filters should help you.

Building RESTful API with MVC for an iPhone app - How to secure it?

I'm going to be writing the services for an iPhone app being built by a third party vendor.
I'll be using ASP.NET MVC to accept posts and also return JSON formatted data.
My question is, how do you secure it?
Just using an API key perhaps? Would that be enough to ensure that only data from the iPhone apps are allowed to hit the specified services?
I'm sort of struggling with the same concepts myself. I think the first thing is to do HTTPS only, so that it's starting out more secure than not.
Next, it depends on how you're going to do authentication. If all you need is an API key, (to track which entity is accessing the data) that should be fine. If you also want to track user information, you'll need some way to associate that specific API keys can access specific types of records, based on a join somewhere.
I'm looking at doing forms auth on my app, and using an auth cookie. Fortunately ASP.NET on IIS can do a lot of that heavy lifting for you.
Example time: (I'm sure I'll need to add more to this, but while I'm at work it gives something to gnaw on)
Forms auth:
Send a pair (or more) of fields in a form body. This is POST through and through. There's no amount of non-reversible hashing that can make this secure. To secure it you must either always be behind a firewall from all intruding eyes (yeah right) or you must be over HTTPS. Simple enough.
Basic auth:
Send a base64 encoded string of "username:password" over the wire as part of the header. Note that base64 is to secure as a screen door is to a submarine. You do not want it to be unsecured. HTTPS is required.
API key:
This says that an app is supposedly XYZ. This should be private. This has nothing to do with users. Preferably is that at the time that the API key is requested, a public key is shared with the API grantor, allowing the API key to be encoded on transit, thus ensuring that it stays private but still proves the source as who they are. This can get complicated, but because there is an application process and because it won't change from the vendor, this can be done over HTTP. This does not mean per-user, this means per-developing-company-that-uses-your-api.
So what you want to have happen is that for the app accessing your data, that you want to make sure it's an authorized app, you can do negotiation using private keys for signing at runtime. This ensures that you're talking to the app you want to talk to. But remember, this does not mean that the user is who they say they are.
HOWEVER.
What you can do is you can use the API key and the associated public/private keys to encode the username and password information for sending them over the wire using HTTP. This is very similar to how HTTPS works but you're only encrypting the sensitive part of the message.
But to let a user track their information, you're going to have to assign a token based on login based on a user. So let them login, send the data over the wire using the appropriate system, then return some unique identifier that represents the user back to the app. Let the app then send that information every time that you are doing user specific tasks. (generally all the time).
The way you send it over the wire is you tell the client to set a cookie, and all the httpClient implementations I've ever seen know that when they make a request to the server, they send back all cookies the server has ever set that are still valid. It just happens for you. So you set a cookie on your response on the server that contains whatever information you need to communicate with the client by.
HTH, ask me more questions so we can refine this further.
One option would be to use forms authentication and use the authentication cookie. Also, make sure all the service calls are being sent over SSL.

Resources