I'm using identity server 3 and want to know if there is any risk using client secret from JavaScript to be able to use Password token grant.
Edit
answer from Scott Brady
Then you'll also know that the implicit flow returns an access token and that the ROPC flow is insecure and deprecated. By stealing a client secret, other apps can impersonate your app, making phishing very simple. Your token endpoint becomes a public endpoint that anyone can use to validate your user's credentials https://www.scottbrady91.com/OAuth/Why-the-Resource-Owner-Password-Credentials-Grant-Type-is-not-Authentication-nor-Suitable-for-Modern-Applications
If it's JavaScript running in the browser, then your secret is not secret anymore.
JavaScript running in the browser is considered a public client. The implicit flow was explicitly designed for your scenario.
Related
My application is mainly based on spring boot micro services. Currently it uses OAuth with password grant_type which is deprecated in the latest spring security authorization server release. For receiving JWT token, it stores client id and client secret in React JS frontend which is not secure and not recommended. Users need to register to access certain resources and application maintains login credentials in mysql DB
I am trying to upgrade spring security and want 'account service' to act as authorization server to issue JWT tokens.
Am I correct in my understanding that I need to use authorization_code grand type with PKCE?
If I use PKCE then I do not need users to provide passwords while registering, is that correct? Storing only username/email should suffice because users just need to pass client ID and code_challenge to get authorization code?
Am I correct in my understanding that I need to use authorization_code grand type with PKCE?
The newest version of Spring Security mode introduces a new project for the Authorization server in the scope of Spring Security:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
<version>0.3.1</version>
</dependency>
The authorization server from spring implements OAuth2.1 where as you mentioned, both PASSWORD and IMPLICIT grant types were removed comparing it to OAuth 2.0.
Gran types supported in OAuth 2.1: 1
Authorization code + PKCE
client credentials
device grant type
OAuth 2.1 provide authorization code + PKCE grant type but it's a little bit different from the previous.
"The key difference between the PKCE flow and the standard
Authorization Code flow is users aren’t required to provide a
client_secret. (...) In place of the client_secret, the client app
creates a unique string value, code_verifier, which it hashes and
encodes as a code_challenge. When the client app initiates the first
part of the Authorization Code flow, it sends a hashed
code_challenge."
2
That type of grant type is recommended for SPA application so if you want to use the newest version of spring security you need to use it, because e.g. client credentials are reserved for machine-to-machine communication when one service needs to communicate with another service without of user's knowledge.
If I use PKCE then I do not need users to provide passwords while registering, is that correct?
Users need to authenticate themselves and that's a part of this grant-type flow.
Storing only username/email should suffice because users just need to pass client ID and code_challenge to get an authorization code?
ClientID and generated code_challenge (should be generated by the client) is something that identifies the client not the resource owner, so user while authorized shouldn't provide this type of info.
Authorizing client request
With OAuth2, clients (your React app) must authorize requests to protected resources, that is provide an access-token as Bearer Authorization header.
When acting on behalf of a user, clients should use authorization-code flow (with PKCE) to fetch such an access-token from authorization-server.
Also, use an OAuth2 client library in your React app. It will help you to:
redirect users to authorization-server
handle redirection back from authorisation-server with authorization code
exchange authorization code for tokens (access, refresh and ID)
Some libs even handle:
access token silent refresh before it expires
request Authorization to configured routes (add access token as header)
automatically trigger login when a user tries to access protected parts of the app.
I have not enough experience with React to recommend a specific lib, but you can search with "OpenID", "OIDC" or even "OAuth2" keywords
Configuring spring REST APIs
REST APIs secured with OAuth2 are "resource-servers". You can use spring-boot-starter-oauth2-resource-server directly as done in the first of those tutorials, but it is quite some Java conf.
Instead, you can use one of the spring-boot starters from the same repo. They are thin wrappers around spring-boot-starter-oauth2-resource-server with sensible defaults and most security conf from properties:
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<!-- replace "webmvc" with "webflux" if your app is a servlet -->
<!-- replace "jwt" with "introspecting" to use token introspection instead of JWT decoding -->
<artifactId>spring-addons-webmvc-jwt-resource-server</artifactId>
<!-- this version is to be used with spring-boot 3.0.0-RC2, use 5.x for spring-boot 2.6.x or before -->
<version>6.0.5</version>
</dependency>
#EnableMethodSecurity
public static class WebSecurityConfig { }
com.c4-soft.springaddons.security.issuers[0].location=https://localhost:8443/realms/master
com.c4-soft.springaddons.security.issuers[0].authorities.claims=realm_access.roles,ressource_access.some-client.roles
com.c4-soft.springaddons.security.cors[0].path=/some-api
Configuring the gateway
Basically, nothing to do in regard to authentication and OAuth2: inbound requests to secured resources should have an authorization header already and resource-servers will respond with 401 if authentication is missing or invalid (expired, wrong issuer, ...) or 403 if access is denied (valid identity but not allowed to access that resource)
authorization-server
Any OAuth2 authorization-server would do, but you might choose an OIDC implementation.
Authorization-server will handle users registration, login and logout. It will issue access, refresh and ID tokens, using mainly:
authorization-code flow for clients acting on behalf of a user
client-credential flow for trusted programmatic client acting in their own name (not on behalf of a user)
refresh-token: if offline_access scope is requested when authenticating (with any flow), a refresh-token is returned in addition to access-token and can be used to silently get a new access-token when current expires (or just before it does)
You can use Spring authorization-server framework to build your own authorization-server, but could also prefer to pick one "off the shelf": there are plenty out there with a lot of features implemented
connect to LDAP and "social" identity providers (Google, Facebook, Github, etc.)
enhance security with multi-factor authentication
provide with admin UI for stuff like user roles or tokens content
...
And this either on premise (Keycloak is a quite popular sample) or SaaS (like Auth0 and many others: almost any cloud provider has its own solution).
I have a react web application with a flask api (I used to use express). The product of this app is the data that it displays. I don't want other people to be able to take that data easily from calling the api.
I want to secure the api such that it can only be accessed by my react app and nothing else. How can I do that?
The only way to truly secure your API is by authenticating your app's user with something like Oauth2 and verify that credential on server-side with something like passport, and make the authorization expire with sessions. AND use SSL so none of that is easily visible through a protocol analyzer.
Sure, you can hard-code some sort of "secret key" with the app, but anyone who want it bad enough will read it off your app or sniff the packets through a packet logger until they find the key.
EDIT: Oh, and as a part of the authorization upon login, provide them with a uniquely generated "API-KEY" as part of identity, so you can validate them upon submission, and if they violate your trust, mark their API key invalid in the server so they can't use them any more.
First, if your client code and API server are running on different domains or ports, configure CORS on your API server to only honor requests that originate from the client code's domain. Second, authenticate legitimate users so that only authorized requests for data are honored. There are lots of 3rd-party libraries to help with authentication.
I'm using Identity Server 4 to authenticate users with WebAuthN (https://w3c.github.io/webauthn/).
I have multiple clients that that hit an api client. My api client is responsible for deciding which auth provider to use, passing data (server to server, server to external api) and orchestrating the auth process.
One auth provider we are using that we own is identity server 4 and this is where we are implementing WebAuthN.
I'm not sure which is the recommended way to implement this in Identity Server 4. I'm down to 2 options
Create an API endpoint on identity server to authenticate to users credential
Create an extension grant type and call the TokenEndpoint API using the new grant type (my extension grant type would be a mix of the built in Hybrid grant type followed by the WebAuthN code).
Are both ways valid from a security standpoint (not opening up a hole) and fit with ID4 or is there another way?
I've recently done some work on implementing this, but for second-factor only at this point.
Long story short, it needs to run in the context of the end user's browser (given that it's a JavaScript API) so really it needs to be built into the sign in flow via the authorize endpoint.
For example (assuming no local client or IDP sessions already exist):
User visits client application
Client redirects to authorize endpoint
Authorize endpoint redirects to interactive authentication UI which then decides what method to use
Do the WebAuthn challenge, validate the result and establish a session cookie
Redirect back to authorize endpoint
Issue tokens and redirect back to client
You'll also need to provide a way for users to register their authenticators. The resulting credentials are tied to the site origin so this must be done within your identityserver4 implementation - the same application that will be doing the challenging.
I have a REST backend secured with OAuth2 and a mobile application.
I would like to use the Resource Owner Credentials flow to authenticate the user from my mobile application.
Since I must provide a client_id to identify the application which is requesting authentication, how can I prevent a hacker to steal my client_id from my mobile application source code, and how can I revoke it ?
I really would like to know how the official Twitter Android application for example handle this kind of thing.
I know this is a very old post, but I just came across it in an unrelated search and saw it was unanswered.
To quote from the OAuth 2.0 spec,
The client identifier is not a secret; it is exposed to the resource owner and MUST NOT be used alone for client authentication.
In other words, the client_id is very similar to a username or email. I certainly wouldn't mind if someone found out my email address, even though that is half of the data required to log in and view my emails. To keep to that idea, the client_secret is a password that should be kept private through guarding your source code and sending POST requests only to HTTPS endpoints.
As for revoking privileges granted to clients through those credentials, most (if not all) major OAuth providers will allow you to do something through their OAuth portal. To follow your Twitter example, they have a button on the API Keys page to "Regenerate API Keys." If you are the service provider (I say this because you mentioned having permissions to Resource Owner Credentials) and you don't have a public-facing OAuth portal set up, it would be simply a matter of changing the strings in whatever data-store you use server-side, then making the same change in your client source code.
I'm about to start a project with WPF which uses a web service to get info etc.
A username and password is required to authenticate you and get data which belongs to you.
I would like my WPF application to store the username and password. But I don't want to store it. So I was thinking. It would be cool if after I login for the first time it would generate a certificate at the WCF end and give it to the WPF application which can be used for each and every call.
Is what I'm thinking possible? Another problem I would like to tackle is how do I avoid someone copying and pasting the certificate?
Update
Based on #zamd suggestion. This is what I would like to solve.
Webservice uses WCF Web Api
Site has forms authentication
Site signs in with Username and Password which is validated by a Token Service
Webservice can authenticate the users token provided by the Token Service
I found this very useful blog article http://weblogs.asp.net/cibrax/archive/2011/02/04/authenticating-clients-in-the-new-wcf-http-stack.aspx but I would like to use Forms Authentication to get the SAML Token
You should look into Claims-based-security and SAML Token.
At login, you application should go to your service or a 'security service' also known as 'Security Token Service' and get a SAML token in exchange of a userName/Password pair. SAML tokens are usually secured for the receipient and can be safely stored on the client side until they are expired.
Every time you need to call WCF service, you can use this SAML token for rich authentiction and authorization.
Your understanding of Certificate base authentication is incorrect. Certificates are used for establishing SSL connection, are used to encrypt data using asymmetric encryption and authenticate user but to authenticate user against a certificate the certificate should be installed on the user's system and not provided by the WCF service. This requires one to setup a PKI infrastructure.
The other options you can look at is to use
ASP.Net form authentication with running WCF service in ASP.Net compatibility mode. In this case once authenticated only the auth cookie would pass there after.
Look at this question for some other ways User/Pass Authentication using RESTful WCF & Windows Forms
If you have to use username/password combination then you can get Windows to store it for you under Windows 7, Windows Server 2008 (and perhaps Vista) using the Windows Credential Manager. You need to fall down to p/invoke calls (
http://pinvoke.net/default.aspx/advapi32/CredRead.html and http://pinvoke.net/default.aspx/advapi32/CredWrite.html) for this.
The only issue I had with this is that it didn't work on Windows Server 2003 even though the documentation says that it is a supported OS.