OAuth responses require a User Pool defined in config - reactjs

I am unable to connect to userpool which I defined right above: Auth is an amplify Object
Auth.configure({
region: process.env.REACT_APP_AWS_REGION,
userPoolId: process.env.REACT_APP_PROD_UNIFY_COGNITO_USER_POOL_ID,
userPoolWebClientId: process.env.REACT_APP_PROD_UNIFY_COGNITO_CLIENT_ID,
// Cognito Hosted UI configuration
oauth: {
domain: process.env.REACT_APP_PROD_UNIFY_COGNITO_DOMAIN,
scope: ['email', 'openid', 'aws.cognito.signin.user.admin', 'profile'],
redirectSignIn: 'http://localhost:3000',
redirectSignOut: 'http://localhost:3000',
responseType: 'code',
},
});
I get this error in my browser :Unhandled Rejection (Error): OAuth responses require a User Pool defined in config
AuthClass.
What else is there to connecting programmatically to a user pool. I didn't do amplify push,add auth or anything with the amplify cli b/c I don't think it's necessary?

This is most often down to the fact that you have changed your .env file, but not stopped and restarted your local web server.
For instance if you use yarn serve, make sure you stop the process, then update your .env, then yarn serve again.

Related

How to configure a react capacitor app running on mobile by usb to make http request to sendbird as localhost instead of its IP address?

I have a React webapp that I have converted it to native app using Capacitor. For live reloading, I had to edit capacitor.config.json as follows:
const config: CapacitorConfig = {
//
webDir: 'build',
bundledWebRuntime: false,
server: {
url: 'http://192.XXX.XXX:3000',
cleartext: true
},
};
This works just fine until the app makes a request to sendbird for initialization. I get the error message: 'SendBirdCall needs https connection, except for 'localhost' or '127.0.0.1'. I tried to setup an express https server but failed. Later I created two channels using ngrok - one for the server and one for the app. The sendbird request was successful but the graphql websocket was failing as ngrok does not support websocket links, also tried a tcp link but it failed as well.
I have another app that I created using the Sendbird React Native Quickstart project and I did not need to do any configuration for that. What could be done in order to make sendbird request using localhost from mobile connected via usb while also being able to have a ws connection?
Try to change the url:
const config: CapacitorConfig = {
...
server: {
url: 'http://localhost:3000',
cleartext: true
},
};
And after connecting a physical device execute the following:
cd $ANDROID_HOME/platform-tools
./adb reverse tcp:3000 tcp:3000
Where $ANDROID_HOME is the Android SDK directory.

.Net 6 react SPA and windows authentication does not get username

I have a default react SPA page made with visual studio 2022 and im using windows authentication. My app will run only on an IIS hosted intranet app.
At my Program.cs, i have configured the authentication and authorization:
builder.Services.AddControllersWithViews();
builder.Services.AddAuthentication();
builder.Services.AddAuthorization();
builder.Services.AddHttpContextAccessor();
builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = NegotiateDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = NegotiateDefaults.AuthenticationScheme;
}).AddNegotiate();
app.UseAuthentication();
app.UseAuthorization();
To test, i created a method app.Use to capture the username, and when i run it with the IISExpress profile, i can get the logged windows user successfully at the homepage
The breakpoint on the if clause is hit in every request on the application
app.Use(async (context, next) =>
{
    if (!context.User.Identity.IsAuthenticated)
    {
        await context.ChallengeAsync();
        await next();
    }
    else
    {
        
        await next();
    }
});
But when i call an endpoint to the example "weatherForecastcontroller" or i dont get the logged user on the httpContext, or the page sends me an Error 401.2 - Unauthorized. I also set up the credentials on the fetch call to "include"
    async populateWeatherData() {
      const response = await fetch('weatherforecast', { "credentials": "include" });
  const data = await response.json();
  this.setState({ forecasts: data, loading: false });
}
I also have set the launchsettings.json to accept only the windows authentication
"iisSettings": {
  "windowsAuthentication": true,
  "anonymousAuthentication": false,
  "iisExpress": {
    "applicationUrl": "http://localhost:53168",
    "sslPort": 44381
  }
Tried also to change the InProcess to OutOfProcess build and the same error occurs
Also, i created an mini web.config, to setup the security tag to allow windows authentication and tried to modiffy the .vs folder .vs<app>\config\applicationhost.config to change de windows and anonymous auth configs
If i use an MVC project on the same machine, it works like a charm, i think there's an proxy or another thing on SPAProxy that bugs things up
What am I missing to successfully get those credentials, any tips or workarounds?
Well, after many googling and testing, i came with a workaround:
The http-proxy-middleware mix up the request headers, and .Net Core does not let authorize, whathever i do;
Configure Authentication and enable cors in Program.cs, allowing it in all application, or just in the controllers that needs to be authenticated. The url in withorigins is the react development server. For a real application, use appSettings.<Development/Staging/Production>.json approach and include that variable as an array of strings of adresses. For debug in local IIS and in production environment, install the IIS Cors Module, downloading it by Microsoft
Program.cs
builder.Services.AddCors(options =>
{
options.AddPolicy("Padrao", builder =>
{
builder
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.WithOrigins("https://localhost:44431");
});
});
builder.Services.AddAuthentication(configureOptions =>
{
configureOptions.DefaultAuthenticateScheme = NegotiateDefaults.AuthenticationScheme;
configureOptions.DefaultChallengeScheme = NegotiateDefaults.AuthenticationScheme;
}).AddNegotiate();
builder.Services.AddAuthorization();
var app = builder.Build();
Use the environment variable in React, to inject the desired backend host as the address. IMPORTANT: That variable needs to have whe REACT_APP_ prefix to the front end read it. Learned from jasonwatmore.com
.env.development
PORT=44431
HTTPS=true
REACT_APP_ASPNETCORE_URLS="https://localhost:44375/"
.env
REACT_APP_ASPNETCORE_URLS="https://localhost/testreact/"
Use the fetch with credentials and keep-alive headers
async populateWeatherData() {
const response = await fetch(process.env.REACT_APP_ASPNETCORE_URLS +'weatherforecast', {
method: "GET",
mode:'cors',
credentials: 'include',
headers: {
"Connection": 'keep-alive',
}
});
const data = await response.json();
this.setState({ forecasts: data, loading: false });}
Allow windows authentication and disable anonymous authentication. You will need to run the app as IISExpress profile, or create a IIS profile to debug, change it in launchsettings.json
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": true,
"iis": {
"applicationUrl": "http://localhost/testereact",
"sslPort": 443
},
"iisExpress": {
"applicationUrl": "http://localhost:43938",
"sslPort": 44375
}
To allow Vs20220 to run in Local IIS, install de IIS Integration on the Visual Studio Installer. With this approach, you will need to call npm start in your /Clientapp by the Powershell command prompt (i didn't make it do call by himself)
I still do not tested this approach in production environment with a real application, but this solves the issue

Google Oauth2 giving "redirect_uri_mismatch" error in production when redirect uri setup correctly

I have google oauth set up in a react project. It was working fine in development, locally. Once i promoted the oauth client to "production" and modified the JS origin and redirect URIs to production values, yet it gives this error
Error 400: redirect_uri_mismatch
You can't sign in to this app because it doesn't comply with Google's
OAuth 2.0 policy.
If you're the app developer, register the redirect URI in the Google
Cloud Console. Request details:
redirect_uri=http://super-server.herokuapp.com/v1/auth/google/callback
Related developer documentation
These are the authorized redirect URIs within google cloud console:
https://super-server.herokuapp.com/v1/auth/google/callback
https://super-server.herokuapp.com/v1/auth/google/callback/
https://www.super-server.herokuapp.com/v1/auth/google/callback
https://www.super-server.herokuapp.com/v1/auth/google/callback/
As you can see, there are no authorized uri's with an HTTP schema. Theyre not even allowed in production mode. So im not sure where this is coming from, because the server is HTTPS
server:
Any advice?
the redirect uri must exactly match the one you are adding to Google developer console
If you check the error message your app is running with
http://super-server.herokuapp.com/v1/auth/google/callback
All the ones you have added are https
May i suggest fixing your app so that it runs https. I dont think that you will be able to add http as a production redirect uri endpoint.
documentation
Obtaining OAuth 2.0 access tokens
authorization-errors-redirect-uri-mismatch
Node.js
I dont know enough about react.js but with node you should be able to do something like this
const http = require('http');
const https = require('https');
In my case (MERN + passport.js), i had a configuration that looked like:
const googleOptions = {
clientID: config.google.id,
clientSecret: config.google.secret,
passReqToCallback: true,
callbackURL: '/v1/auth/google/callback',
scope: ['profile', 'email']
};
Even though the server, the client && the configuration of the oauth client within google api console were all in production with everything setup for https, for some reason, the callbackURL kept firing with google oauth as http://my-domain.com/v1/auth/google/callback
so this fix may be hacky, but it did fix my oauth issues:
//Google Strategy
const googleOptions = {
clientID: config.google.id,
clientSecret: config.google.secret,
passReqToCallback: true,
callbackURL: config.environment == 'production' ? 'https://super-server.herokuapp.com/v1/auth/google/callback' : '/v1/auth/google/callback',
scope: ['profile', 'email']
};
Looks like the redirect_uri on the client side (React side) is set to http://super-server.herokuapp.com/v1/auth/google/callback
Change the redirect_uri on the client side from (http) http://super-server.herokuapp.com/v1/auth/google/callback to (https) https://super-server.herokuapp.com/v1/auth/google/callback.

ReactJS proper configuration of OIDC on Kong + Keycloak

I am wondering what should be the proper configuration when I have the ReactJS front end application and I want to give access to BE only to authorized and authenticated users through OIDC.
I have the following setup:
Browser ----> Kong ----> /admin* (ReactJS FE)
----> /api* (BE REST API)
|
Keycloak
The goal here is that the Kong will do the authorization and authentication so it can be externalized from the application.
Kong is using OIDC plugin that can handle authorization when the user would like to open application in browser and is not authorized. It will redirect to Keycloak, and once user is authorized, it will come back to Kong for further processing of JWT token.
This will happen when user hits for example https://localhost:8000/admin. So far, so good.
Now, the actual functionality is provided by the /api* end points. Therefore I need to get the token or cookie and be able to validate the token to have access to the API (here we are authenticating user).
What is the proper way how to configure this? Should be the API also protected by OIDC with the same flow, or it should only validate JWT.
The first option, when the /api* has the OIDC plugin enabled:
open https://localhost:8000/admin with unauthorized user
Kong will detect it and use the OIDC plugin to authorize through Keycloak
browser is redirected to Keycloak, user will provide credentials
browser will send info about authorization back to Kong, and it will finish authorization and get the JWT token
from now on, the ReactJS FE will use cookies and eventually JWT token to access the https://localhost:8000/api* from the ReactJS application
Now, when the access is expired or revoked, and the ReactJS application is still opened, I get errors, because the OIDC plugin will try to redirect on /api* calls with 302, however I am still in the ReactJS app, and it cannot handle it. The only way here is to refresh the complete ReactJS app and it will do the authorization again and it will work.
Here, I am utilizing kong-oidc plugin.
The second option I am thinking about, when the /api* route does not use OIDC plugin, but only validates JWT tokens:
open https://localhost:8000/admin with unauthorized user
Kong will detect it and use the OIDC plugin to authorize through Keycloak
browser is redirected to Keycloak, user will provide credentials
browser will send info about authorization back to Kong, and it will finish authorization and get the JWT token
from now on, the ReactJS FE will use cookies and eventually JWT token to access the https://localhost:8000/api* from the ReactJS application
When the session is expired or revoked, the ReactJS application will start getting the 401 unauthorized instead of 302. In this case, the ReactJS should know that it should start the OIDC again to get new token, or refresh.
In this second options, I can use kong-oidc plugin for OIDC on the ReactJS, and kong-plugin-jwt-keycloak plugin for validation of tokens on the API level.
I currently have the following configuration of Kong, which should be behaving according the first option:
_format_version: '2.1'
_transform: true
services:
- name: core
host: core-service
port: 8080
protocol: http
routes:
- name: core_route-oidc
strip_path: false
paths:
- /api*
plugins:
- name: oidc
config:
client_secret: s0qKH5qItTWoxpBt7Zrj348ZhZ7woAbk
client_id: kong
bearer_only: 'no'
realm: Kong
introspection_endpoint: >-
https://keycloak.local/realms/Kong/protocol/openid-connect/token/introspect
discovery: >-
https://keycloak.local/realms/Kong/.well-known/openid-configuration
- name: request-transformer
config:
remove:
headers:
- cookie
- name: fe-administrator
host: fe-administrator-service
port: 80
protocol: http
path: /
routes:
- name: fe-administrator_route-oidc
strip_path: false
paths:
- /admin*
plugins:
- name: oidc
config:
client_secret: s0qKH5qItTWoxpBt7Zrj348ZhZ7woAbk
client_id: kong
bearer_only: 'no'
realm: Kong
introspection_endpoint: >-
https://keycloak.local/realms/Kong/protocol/openid-connect/token/introspect
discovery: >-
https://keycloak.local/realms/Kong/.well-known/openid-configuration
- name: request-transformer
config:
remove:
headers:
- cookie
plugins:
- name: cors
config:
origins:
- '*'
credentials: true
max_age: 3600
exposed_headers:
- X-Auth-Token
preflight_continue: false
But I am wondering if this is proper configuration. Also, if some client application would like to access only /api*, without accessing the ReactJS front end application, it will not use the same OIDC flow, do I understand it correctly?
Should be the /api* configured according second option and provides validation of JWT tokens only? Something like the following Kong config:
_format_version: '2.1'
_transform: true
services:
- name: core
host: core-service
port: 8080
protocol: http
routes:
- name: core_route-oidc
strip_path: false
paths:
- /api*
plugins:
- name: jwt-keycloak
config:
allowed_iss: >-
https://keycloak.local/realms/Kong
- name: request-transformer
config:
remove:
headers:
- cookie
- name: fe-administrator
host: fe-administrator-service
port: 80
protocol: http
path: /
routes:
- name: fe-administrator_route-oidc
strip_path: false
paths:
- /admin*
plugins:
- name: oidc
config:
client_secret: s0qKH5qItTWoxpBt7Zrj348ZhZ7woAbk
client_id: kong
bearer_only: 'no'
realm: Kong
introspection_endpoint: >-
https://keycloak.local/realms/Kong/protocol/openid-connect/token/introspect
discovery: >-
https://keycloak.local/realms/Kong/.well-known/openid-configuration
- name: request-transformer
config:
remove:
headers:
- cookie
plugins:
- name: cors
config:
origins:
- '*'
credentials: true
max_age: 3600
exposed_headers:
- X-Auth-Token
preflight_continue: false
And the ReactJS application must properly handle 401 unauthorized.
I would like to understand how this should be done properly.
Implementing an SPA secured by cookies is tricky. It is worth comparing against the behaviour of a backend for frontend, the second of the below roles, and basing your solution on that.
URLs
https://www.myapp.com/admin: downloads the index.html for the SPA, and other static resources
https://www.myapp.com/api: a cookie secured API entry point for a particular SPA
https://api.mycompany.com/api: a public API URL that can be called with access tokens
COOKIE API ROUTE
The second URL is called during Ajax requests from the SPA. There should be no OIDC or redirects here, just cookie / token validation and forwarding.
This route should translate cookies to tokens, apply CSRF checks, then forward the token to the API. If the cookie / token is invalid or expired a 401 should be returned. The keycloak plugin you mention expects to receive JWTs, not cookies.
BACKEND FOR FRONTEND
A BFF would run on the second URL and provide endpoints tailored to what the React app needs, such as these:
https://www.myapp.com/bff/login/start: Return a login redirect URL for the SPA
https://www.myapp.com/bff/login/end: Process a login response URL and write cookies
https://www.myapp.com/bff/refresh: Refresh access tokens represented by cookies
https://www.myapp.com/bff/logout/start: Return a logout redirect URL for the SPA
It can be difficult to implement a BFF as an API gateway plugin, so sometimes it is instead implemented as a utility API, which runs behind the gateway.

webpack-dev-server develop on https

My .NET Core API is exposed over https.
I want to do request to API from my React app running on webpack-dev-server. But webpack-dev-server running on http by default and CORS block any requests.
I reconfigure webpack to force use https (with my *.pfx certificate example),
but then i have 'private connection error' in browser at every refresh (minor problem) and auto-refreshing stops working.
console errors:
> [HMR] Waiting for update signal from WDS...
> app.js:4049 WebSocket connection to 'wss://localhost:8080/sockjs-node/826/sy0x5mcu/websocket' failed: Error in connection establishment: net::ERR_INSECURE_RESPONSE
> [WDS] Hot Module Replacement enabled.
I think that websockets of webpack-dev-server can not establish connection because of https url. But i do not know how to fix this.
Proxy your .NET core api in your webpack dev server config
{
proxy: {
'/api/**': {
target: 'https://localhost:443', // or whichever port it's listening on
secure: false,
changeOrigin: true, // this might not be necessary depending on how restrictive your host is
pathRewrite: {'^/api' : ''}, // rewrite request /api/foo -> https://localhost:443/foo
},
}
}
More docs on proxying with webpack dev server:
https://webpack.js.org/configuration/dev-server/#devserverproxy

Resources