Is there a way for a Slack CLI tool to proceed through the V2 OAuth access token flow without standing up an entire web site? - oauth-2.0

I have a CLI tool that requires search access, on behalf of the user. I've set up an application on our team's workspace with all of the right scopes and configuration.
However, I am dismayed at how oppressive the OAuth access token process is for CLI tools. Step 1 in their process is to provide a link to a custom web site that has an "Add to Slack" button. This already extends a simple CLI tool into requiring an entire web site, but the button is merely a static URL with parameters about the app and scopes. So far, a static page from Confluence, GitHub, or some other wiki-based project space would be enough.
Step 2 is where the user grants access to the application through their browser. However, Step 3 is where the action redirects to a special, dynamic page that requires access to take a special code, and translate it into an actual usable token for the user to plug into the CLI configuration. This extra step requires a special web page that Slack does not provide to do the translation, instead of just handing a token directly to the user.
Even worse, the API call requires secret client_id and client_secret parameters that would be plain as day in an shared or open-source CLI tool. (Despite the API documentation saying otherwise, both of these parameters are actually required.)
For example, Slackcat requires a one-page special web site expressly for the purposes of fielding OAuth requests. This is a web page that cannot be opened to the public because it would reveal the secret parameters. Unfortunately, Slackcat does not have the right scope levels I need, so I can't just borrow its web site for token generation.
Is there a better way to sidestep this process and allow a simple CLI tool to just get the right user access token it needs?

OAuth2 is fundamentally built around web browsers. The entire point is to allow the user's web browser to be redirected to the OAuth2 provider's website for password entry, so that the user's credentials are never visible to you or pass through any infrastructure you control.
This necessarily involves spawning a browser and sending it to a site you control to begin the OAuth2 flow by setting up state and redirecting the user to the OAuth2 provider, and then complete the OAuth2 flow by handling the redirect back from the OAuth2 provider and performing the code/token exchange. You can't do any of this with a static site, you need a web service.
Is there a better way to sidestep this process and allow a simple CLI tool to just get the right user access token it needs?
No. If there were, it would be a vulnerability in OAuth2 that should be fixed, not exploited to bypass the entire point of OAuth2.

Related

How to handle authorization and authentication on SPA with OAuth2?

I am developing an SPA and would like to have SSO.
As I understood so far, OAuth2 with OIDC is the best solution for SPA SSO.
Better than, for example, SAML.
What I didn't understand so far is how to use authorization token in SPA's JS code to handle authorization on various resources of SPA. For example, I would like the users with a role 'buyer' to have access to the shopping history tab, where other users won't have access to.
Should I parse access token obtained from Authorization server in JS code and check whether a user has an appropriate role to see the tab, or should this decision be made on server (API) side, in which case SPA's code would just read the answer from API and based on that customize UI?
In case of the first approach, is there any standard way of doing the checking (in form of some JS library)?
When it comes to authentication, what is the better approach (more secure, etc):
to let SPA (at that point already loaded in the browser) do the authentication flow and based on result let the user use it's protected functionalities. This is pseudo authentication actually since the code is in the user's browser and means the user is authenticating himself to the code in his hands i.e. to himself. Does this authentication make sense at all?
require the user to authenticate himself in order to be able to even load the SPA in his browser. This is probably not SPA architecture then since backend which serves the SPA should be able to create a backchannel with the Authentication server.
According to user description, your application must vary depending on user type. If this is the case I would suggest you to use a backend for authentication and decide application content to be served from the backend. Otherwise, as you have figured out, running authentication on browser and altering user view is not secure.
IMO this not necessarily break SPA architecture. What you are doing is altering what you server based on tokens presented to you. Also, maintaining a session will be required with this approach. And SPA's calls for backend will require to contain this session to obtain contents.
As soon as the User is logged in, you would request for authentication and based on his UserId, and the role he belongs to you should receive all the permissions that User is entitled to.
You convert these permissions into claims and can send them back to UI and use it appropriately to show the features accordingly.
You also enforce same on the server side api to prevent any unauthorized access besides from your UI.

Authenticate to external API from a Jira add-on

I am building a Jira add-on that gives provides the user with the status of an object within my own API (not within Jira). My API is protected using OAuth 2.0. What is the best way to authenticate to my API from my Jira add-on?
I like how the Jira + GitHub/Bitbucket integration works. Specifically, the user retrieves API keys from GitHub and puts them in Jira. Jira then uses these keys to authenticate with and then retrieve data from GitHub. At least, this is how I think it works.
How can I achieve this same effect for my Jira add-on?
When you are building a cloud add-on then you can handle authentication without bothering admins (they don't need to copy anything).
To integrate yourself with Jira UI you need to create a webpanel or page, in both cases, Jira will ask your site to render the HTML code and the request will include JWT token. Inside you will have information about which user did the request.
Now, you can authenticate Jira users to your API in several ways:
render a time-limited token to the HTML and use it to authenticate calls to your API. As a downside of this solution, if someone will keep the page open without reloading for long enough (longer than your time limit) the token will become invalid.
provide a resource to retrieve time-limited token (validate JWT signature provided by Jira to be sure request really comes from particular Jira instance) and retrieve the token every time before doing the request (or every N minutes depending on your time limit).
or if you really want to bother admins then create a configuration page and let them save API keys by hand (I assume they will have to retrieve those keys from you somehow, this additional step may discourage many admins), in this configuration page you will include JS code that on submit will save API keys as Application property and later you will have to retrieve this before making requests to your API. With this approach however, admins will not be able to restrict access to your API to a subset of users with Jira permissions (every logged in user can access application properties, in open instances even anonymous users).
If you are unsure how to validate JWT Token you can read this developer guide. Also, you can make your life easier by using one of the provided framework and tools, for example, atlassian-connect-spring-boot will take care of installation handshake, JWT authentication and authentication to Jira REST API from your server.

Logging in with IdentityServer with custom client-side log in page

I have a setup of IdentityServer with configuration of a client with hybrid flow. Is it possible to have an ASP.NET MVC app to use this instance of IdentityServer to log-in the user without looping to IdentityServer's log-in page? That is, use a custom log-in page on the client side to get user credentials and then make a server-side connection with IdentityServer to do the authorization? Is there any sample that demonstrates this? Thanks!
From how I interpret your question, the Resource Owner Password Credential Flow seems to fit your scenario.
See the FAQ-like answer here.
"Q. Which Flow Types designed to be used ONLY in trusted environment (like backend REST API/ micro-services isolated from internet, or owned servers/devices, in general: trusted OAuth2 clients)?
A.
Resource Owner Password Credential Flow (ROPCF) [it involve human: app show its own login page then pass user/pass... to STS].
Client Credential flow [machine to machine (API to API): supply client-id and secret]."
*Disclaimer - I understand you are currently using Hybrid flow- My answer simply implies you could change your solution. If that is not possible, then I would suggest looking into multiple OAuth implementations for an MVC app.
Since I didn't get an answer for this, I'm just posting what I've found so far.
It looks like it is not possible to bypass the IdentityServer's log-in page.
For more info about IdentityServer flows see: OIDC and OAuth2 Flows

How to integrate OAuth with a single page application?

When using OAuth (2) I need a redirection endpoint in my application that the OAuth-offering service can redirect to, once I have been authenticated.
How do I handle this in a single page application? Of course, a redirect to the OAuth-offering service is not nice here, and it may not even be possible to redirect back.
I know that OAuth also supports a username / password based token generation. This works perfectly with an AJAX call, but requires my single page application to ask for a username and password.
How do you usually handle this?
Most of the time, a redirect is okay even for SPA because users don't like to put their X service credentials on any other website than X. An alternative will be to use an small popup window, you can check what Discourse does. IMHO a redirect is better than a popup.
Google Some providers support the resource owner flow which is what you described as sending username and password, but this is not nice. These are the problems I see:
Asking google credentials to users in your site will be a no-go for some users.
The resource owner flows need the client_secret too and this is something that you must NOT put in your client side javascript. If you instantiate the resource owner flow from your server-side application and your application is not in the same geographically region than the user, the user will get a warning "hey someone is trying to access with your credentials from India".
OAuth describes a client-side flow called implicit flow. Using this flow you don't need any interaction in your server-side and you don't need the client_secret. The OAuth provider redirects to your application with a "#access_token=xx". It is called implicit because you don't need to exchange authorization code per access token, you get an access_token directly.
Google implement the implicit flow, check: Using OAuth2 for Client-Side apps.
If you want to use the implicit flow with some provider that doesn't support it like Github, you can use an authentication broker like Auth0.
disclaimer: I work for Auth0.
What José F. Romaniello said is correct. However, your question is broad and thus I feel any offered conclusions are just generalities at this point.
Application state
For example, without knowing how complex your application state is at the time you want to let your users log in, nobody can know for sure if using a redirection is even practical at all. Consider that you might be willing to let the user log in very late in his workflow/application usage, at a point where your application holds state that you really don't want to serialize and save for no good reason. Let alone write code to rebuild it.
Note: You will see plenty of advice to simply ignore this on the web. This is because many people store most of the state of their application in server-side session storage and very little on their (thin) client. Sometimes by mistake, sometimes it really makes sense -- be sure it does for you if you choose to ignore it. If you're developing a thick client, it usually doesn't.
Popup dialogs
I realize that popups have a bad rep on the web because of all their misuses, but one has to consider good uses. In this case, they serve exactly the same purposes as trusted dialogs in other types of systems (think Windows UAC, fd.o polkit, etc). These interfaces all make themselves recognizable and use their underlying platform's features to make sure that they can't be spoofed and that input nor display can't be intercepted by the unprivileged application. The exact parallel is that the browser chrome and particularly the certificate padlock can't be spoofed, and that the single-origin policy prevents the application from accessing the popup's DOM. Interaction between the dialog (popup) and the application can happen using cross-document messaging or other techniques.
This is probably the optimal way, at least until the browsers somehow standardize privilege authorization, if they ever do. Even then, authorization processes for certain resource providers may not fit standardized practices, so flexible custom dialogs as we see today may just be necessary.
Same-window transitions
With this in mind, it's true that the aesthetics behind a popup are subjective. In the future, browsers might provide APIs to allow a document to be loaded on an existing window without unloading the existing document, then allow the new document to unload and restore the previous document. Whether the "hidden" application keeps running or is frozen (akin to how virtualization technologies can freeze processes) is another debate. This would allow the same procedure than what you get with popups. There is no proposal to do this that I know of.
Note: You can simulate this by somehow making all your application state easily serializable, and having a procedure that stores and restores it in/from local storage (or a remote server). You can then use old-school redirections. As implied in the beginning though, this is potentially very intrusive to the application code.
Tabs
Yet another alternative of course is to open a new tab instead, communicate with it exactly like you would a popup, then close it the same way.
On taking user credentials from the unprivileged application
Of course it can only work if your users trust you enough not to send the credentials to your server (or anywhere they don't want them to end up). If you open-source your code and do deterministic builds/minimization, it's theoretically possible for users to audit or have someone audit the code, then automatically verify that you didn't tamper with the runtime version -- thus gaining their trust. Tooling to do this on the web is nonexistent AFAIK.
That being said, sometimes you want to use OAuth with an identity provider under you control/authority/brand. In this case, this whole discussion is moot -- the user trusts you already.
Conclusion
In the end, it comes down to (1) how thick your client is, and (2) what you want the UX to be like.
OAuth2 has 4 flows a.k.a. grant types, each serving a specific purpose:
Authorization Code (the one you alluded to, which requires redirection)
Implicit
Client Credential
Resource Owner Password Credential
The short answer is: use Implicit flow.
Why? Choosing a flow or grant type relies on whether any part of your code can remain private, thus is capable of storing a secret key. If so, you can choose the most secure OAuth2 flow - Authorization Code, otherwise you will need to compromise on a less secure OAuth2 flow. e.g., for single-page application (SPA) that will be Implicit flow.
Client Credential flow only works if the web service and the user are the same entity, i.e., the web service serves only that specific user, while Resource Owner Password Credential flow is least secure and used as last resort since the user is required to give her social login credentials to the service.
To fully understand the difference between recommended Implicit flow and Authorization Code flow (the one that you alluded to and requires redirection), take a look at the flow side-by-side:
This diagram was taken from: https://blog.oauth.io/introduction-oauth2-flow-diagrams/

ASP.NET MVC 2 and authentication using WIF (Windows Identity Foundation)

Are there any decent examples of the following available:
Looking through the WIF SDK, there are examples of using WIF in conjunction with ASP.NET using the WSFederationAuthenticationModule (FAM) to redirect to an ASP.NET site thin skin on top of a Security Token Service (STS) that user uses to authenticate (via supplying a username and password).
If I understand WIF and claims-based access correctly, I would like my application to provide its own login screen where users provide their username and password and let this delegate to an STS for authentication, sending the login details to an endpoint via a security standard (WS-*), and expecting a SAML token to be returned. Ideally, the SessionAuthenticationModule would work as per the examples using FAM in conjunction with SessionAuthenticationModule i.e. be responsible for reconstructing the IClaimsPrincipal from the session security chunked cookie and redirecting to my application login page when the security session expires.
Is what I describe possible using FAM and SessionAuthenticationModule with appropriate web.config settings, or do I need to think about writing a HttpModule myself to handle this? Alternatively, is redirecting to a thin web site STS where users log in the de facto approach in a passive requestor scenario?
An example of WIF + MVC is available in this chapter of the "Claims Identity Guide":
http://msdn.microsoft.com/en-us/library/ff359105.aspx
I do suggest reading the first couple chapters to understand all underlying principles. This blog post covers the specifics of MVC + WIF:
Link
Controlling the login experience is perfectly fine. You should just deploy your own STS (in your domain, with your look & feel, etc). Your apps would simply rely on it for AuthN (that's why a app is usually called a "relying party").
The advantage of the architecture is that authN is delegated to 1 component (the STS) and not spread out throughout many apps. But the other (huge) advantage is that you can enable more sophisticated scenarios very easily. For example you can now federate with other organization's identity providers.
Hope it helps
Eugenio
#RisingStar:
The token (containing the claims) can be optionally encrypted (otherwise they will be in clear text). That's why SSL is always recommended for interactions between the browser and the STS.
Notice that even though they are in clear text, tampering is not possible because the token is digitally signed.
That's an interesting question you've asked. I know that for whatever reason, Microsoft put out this "Windows Identity Foundation" framework without much documentation. I know this because I've been tasked with figuring out how to use it with a new project and integrating it with existing infrastructure. I've been searching the web for months looking for good information.
I've taken a somewhat different angle to solving the problem you describe.
I took an existing log-on application and integrated Microsoft's WIF plumbing into it. By that, I mean that I have an application where a user logs in. The log-on application submits the credentials supplied by the user to another server which returns the users identity (or indicates log-on failure).
Looking at some of Microsoft's examples, I see that they do the following:
Construct a SignInRequestMessage from a querystring (generated by a relying party application), construct a security token service from a custom class, and finally call FederatedSecurityTokenServiceOperations.ProcessSignInresponse with the current httpcontext.response. Unfortunately, I can't really explain it well here; you really need to look at the code samples.
Some of my code is very similar to the code sample. Where you're going to be interested in implementing a lot of your own logic is in the GetOutputClaimsIdentity. This is the function that constructs the claims-identity that describes the logged-in user.
Now, here's what I think you're really interested in knowing. This is what Microsoft doesn't tell you in their documentation, AFAIK.
Once the user logs in, they are redirected back to the relying party application. Regardless of how the log-on application works, the WIF classes will send a response to the user's browser that contains a "hidden" HTML input that contains the token signing certificate and the user's claims. (The claims will be in clear text). At the end of this response is a redirect to your relying-party website. I only know about this action because I captured it with "Fiddler"
Once back at the relying party web site, the WIF classes will handle the response (before any of your code is run). The certificate will be validated. By default, if you've set up your relying party web site with FedUtil.exe (by clicking "Add STS Reference in your relying party application from Visual Studio), Microsoft's class will verify the certificate thumbprint.
Finally, the WIF framework sets cookies in the user's browser (In my experience, the cookie names start out with "FedAuth") that contain the users claims. The cookies are not human readable.
Once that happens, you may optionally perform operations on the user's claims within the relying party website using the ClaimsAuthenticationClass. This is where your code is running again.
I know this is different from what you describe, but I have this setup working. I hope this helps!
ps. Please check out the other questions I've asked about Windows Identity Foundation.
UPDATE: To answer question in comment below:
One thing that I left out is that redirection to the STS log-on application happens by way of a redirect with a query-string containing the URL of the application the user is logging in to. This redirect happens automatically the first time a user tries to access a page that requires authentication. Alternatively, I believe that you could do the redirect manually with the WSFederationAuthentication module.
I've never tried to do this, but if you want to use a log-on page within the application itself, I believe the framework should allow you to use the following:
1) Encapsulate your STS code within a library.
2) Reference the library from your application.
3) Create a log-on page within your application. Make sure that such page does not require authentication.
4) Set the issuer property of the wsFederation element within the Microsoft.IdentityModel section of your web.config to the login page.
What you want to do is an active signin. WIF includes WSTrustChannel(Factory) which allows you to communicate directly with the STS and obtain a security token. If you want your login form to work this way, you can follow the "WSTrustChannel" sample from the WIF 4.0 SDK. Once you have obtained the token, the following code will take that token and call the WIF handler to create a session token and set the appropriate cookie:
public void EstablishAuthSession(GenericXmlSecurityToken genericToken)
{
var handlers = FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlers;
var token = handlers.ReadToken(new XmlTextReader(
new StringReader(genericToken.TokenXml.OuterXml)));
var identity = handlers.ValidateToken(token).First();
// create session token
var sessionToken = new SessionSecurityToken(
ClaimsPrincipal.CreateFromIdentity(identity));
FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
}
Once you have done this, your site ought to behave the same as if passive signing had occurred.
You could use the FederatedPassiveSignIn Control.
Setting your cookie like this:
FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
Doens't work for SSO to other domains.
To cookie should be set by the STS not at the RP.

Resources