NestJS Swagger Authentication For accessing docs [duplicate] - swagger

This question already has answers here:
Is it possible to add Authentication to access to NestJS' Swagger Explorer
(13 answers)
Closed 12 months ago.
I have built a project using NestJS along with #nestjs/swagger and swagger-ui-express for API documentation.
Now my docs can be accessible at this path /api/docs but this is absolutely public anyone can access it once I will deploy it to the cloud but I don't wanna do this although most of API's require Bearer token, unfortunately, some of them will remain publically exposed.
Is there any way I can have a login screen for authenticating users before they access my swagger docs?
Here is my code for setting up docs:
import { INestApplication } from '#nestjs/common';
import { SwaggerModule, DocumentBuilder } from '#nestjs/swagger';
import {
SWAGGER_API_ROOT,
SWAGGER_API_NAME,
SWAGGER_API_DESCRIPTION,
SWAGGER_API_CURRENT_VERSION,
} from './constants';
export const setupSwagger = (app: INestApplication) => {
const options = new DocumentBuilder()
.setTitle(SWAGGER_API_NAME)
.setDescription(SWAGGER_API_DESCRIPTION)
.setVersion(SWAGGER_API_CURRENT_VERSION)
.addBearerAuth()
.build();
const document = SwaggerModule.createDocument(app, options);
SwaggerModule.setup(SWAGGER_API_ROOT, app, document);
};

What if you only set the docs in dev mode?
You can create an environment var DEV = true or false. After deploy, set it to false and validate with:
if (process.env.DEV) {
export const setupSwagger = (app: INestApplication) => {
const options = new DocumentBuilder()
.setTitle(SWAGGER_API_NAME)
.setDescription(SWAGGER_API_DESCRIPTION)
.setVersion(SWAGGER_API_CURRENT_VERSION)
.addBearerAuth()
.build();
const document = SwaggerModule.createDocument(app, options);
SwaggerModule.setup(SWAGGER_API_ROOT, app, document);
};
}
Just and idea

Related

Is there a way to deploy a Lex bot using CDK?

I want to deploy a Lex bot to my AWS account using CDK.
Looking at the API reference documentation I can't find a construct for Lex. Also, I found this issue on the CDK GitHub repository which confirms there is no CDK construct for Lex.
Is there any workaround to deploy the Lex bot or another tool for doing this ?
Edit: CloudFormation support for AWS Lex is now available, see Wesley Cheek's answer. Below is my original answer which solved the lack of CloudFormation support using custom resources.
There is! While perhaps a bit cumbersome, it's totally possible using custom resources.
Custom resources work by defining a lambda that handles creation and deletion events for the custom resource. Since it's possible to create and delete AWS Lex bots using the AWS API, we can make the lambda do this when the resource gets created or destroyed.
Here's a quick example I wrote in TS/JS:
CDK Code (TypeScript):
import * as path from 'path';
import * as cdk from '#aws-cdk/core';
import * as iam from '#aws-cdk/aws-iam';
import * as logs from '#aws-cdk/aws-logs';
import * as lambda from '#aws-cdk/aws-lambda';
import * as cr from '#aws-cdk/custom-resources';
export class CustomResourceExample extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Lambda that will handle the different cloudformation resource events
const lexBotResourceHandler = new lambda.Function(this, 'LexBotResourceHandler', {
code: lambda.Code.fromAsset(path.join(__dirname, 'lambdas')),
handler: 'lexBotResourceHandler.handler',
runtime: lambda.Runtime.NODEJS_14_X,
});
lexBotResourceHandler.addToRolePolicy(new iam.PolicyStatement({
resources: ['*'],
actions: ['lex:PutBot', 'lex:DeleteBot']
}))
// Custom resource provider, specifies how the custom resources should be created
const lexBotResourceProvider = new cr.Provider(this, 'LexBotResourceProvider', {
onEventHandler: lexBotResourceHandler,
logRetention: logs.RetentionDays.ONE_DAY // Default is to keep forever
});
// The custom resource, creating one of these will invoke the handler and create the bot
new cdk.CustomResource(this, 'ExampleLexBot', {
serviceToken: lexBotResourceProvider.serviceToken,
// These options will be passed down to the lambda
properties: {
locale: 'en-US',
childDirected: false
}
})
}
}
Lambda Code (JavaScript):
const AWS = require('aws-sdk');
const Lex = new AWS.LexModelBuildingService();
const onCreate = async (event) => {
await Lex.putBot({
name: event.LogicalResourceId,
locale: event.ResourceProperties.locale,
childDirected: Boolean(event.ResourceProperties.childDirected)
}).promise();
};
const onUpdate = async (event) => {
// TODO: Not implemented
};
const onDelete = async (event) => {
await Lex.deleteBot({
name: event.LogicalResourceId
}).promise();
};
exports.handler = async (event) => {
switch (event.RequestType) {
case 'Create':
await onCreate(event);
break;
case 'Update':
await onUpdate(event);
break;
case 'Delete':
await onDelete(event);
break;
}
};
I admit it's a very bare-bones example but hopefully it's enough to get you or anyone reading started and see how it could be built upon by adding more options and more custom resources (for example for intentions).
Deploying Lex using CloudFormation is now possible.
CDK support has also been added but it's only available as an L1 construct, meaning the CDK code is basically going to look like CloudFormation.
Also, since this feature just came out, some features may be missing or buggy. I have been unable to find a way to do channel integrations, and have had some problems with using image response cards, but otherwise have successfully deployed a bot and connected it with Lambda/S3 using CDK.

How to get Client parameter for google_api from firebase auth [duplicate]

I want to use Google Cloud Natural Language in my Flutter app,I got Google API package
This works for flutter and theGoogle API_AUTH dependence is working for 0.2.1.
How do I implement them ?
This worked for me:
Logging in using package google_sign_in and then get auth headers from it:
import 'package:google_sign_in/google_sign_in.dart'
show GoogleSignIn, GoogleSignInAccount;
import 'package:googleapis/people/v1.dart'
show ListConnectionsResponse, PeopleApi;
useGoogleApi() async {
final _googleSignIn = new GoogleSignIn(
scopes: [
'email',
'https://www.googleapis.com/auth/contacts.readonly',
],
);
await _googleSignIn.signIn();
final authHeaders = _googleSignIn.currentUser.authHeaders;
// custom IOClient from below
final httpClient = GoogleHttpClient(authHeaders);
data = await PeopleApi(httpClient).people.connections.list(
'people/me',
personFields: 'names,addresses',
pageToken: nextPageToken,
pageSize: 100,
);
}
This is a custom IOClient implementation that automatically adds the auth headers to each request. The googleapis call support passing a custom HTTP client to be used instead of the default (see above)
import 'package:http/io_client.dart';
import 'package:http/http.dart';
class GoogleHttpClient extends IOClient {
Map<String, String> _headers;
GoogleHttpClient(this._headers) : super();
#override
Future<StreamedResponse> send(BaseRequest request) =>
super.send(request..headers.addAll(_headers));
#override
Future<Response> head(Object url, {Map<String, String> headers}) =>
super.head(url, headers: headers..addAll(_headers));
}
I can't add comments yet, so I'll just post it as an answer.
I kept trying to make a GoogleHttpClient as per the top answer, but on the import, it says "The library 'package:http/http.dart' doesn't export a member with the shown name 'IOClient'."
I found the answer here https://pub.dartlang.org/packages/http#-changelog-tab-, which says you should import IOClient separately as such: import 'package:http/io_client.dart';
I thought this might help out others who are new to flutter and its implementation of Google APIs.
The accepted answer is most likely written towards an older version of the SDK I just couldn't get it to work. This is what works for me as of now.
As an example, the following allow us to access files in Google Drive which is part of googleapis.
Dependencies
pubspec.yaml:
dependencies:
google_sign_in: any
googleapis: any
(I just put any here as a example, but you should specific the version(s) for you actual app.)
How it works
Necessary imports:
import 'package:googleapis/drive/v3.dart' as drive;
import 'package:google_sign_in/google_sign_in.dart' as signIn;
Step 1, sign in the user and ask for access permission (scope) to google drive:
final googleSignIn = signIn.GoogleSignIn.standard(scopes: [drive.DriveApi.DriveScope]);
final sign.GoogleSignInAccount account = await googleSignIn.signIn();
Step 2, build a AuthenticateClient:
class AuthenticateClient extends http.BaseClient {
final Map<String, String> headers;
final http.Client client;
AuthenticateClient(this.headers, this.client);
Future<http.StreamedResponse> send(http.BaseRequest request) {
return client.send(request..headers.addAll(headers));
}
}
As suggested in http, this is using the BaseClient with extra authentication headers (being composable).
Step 3, create a authenticated http client with from step 1 and 2 and access google drive API.
final baseClient = new Client();
final authenticateClient = AuthenticateClient(authHeader, baseClient);
final driveApi = drive.DriveApi(authenticateClient);
Checkout How to Use the Google Drive API With Flutter Apps for details.
Update to the accepted answer
Along with google_sign_in and googleapis packages, now you can use extension_google_sign_in_as_googleapis_auth package (provided by flutter.dev) to get configured http client. So the accepted answer can be simplified to below. No implementation of GoogleHttpClient is necessary.
import 'package:extension_google_sign_in_as_googleapis_auth/extension_google_sign_in_as_googleapis_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:googleapis/people/v1.dart';
useGoogleApi() async {
final _googleSignIn = new GoogleSignIn(
scopes: [
'email',
PeopleServiceApi.contactsReadonlyScope,
],
);
await _googleSignIn.signIn();
// custom IOClient
final httpClient = await _googleSignIn.authenticatedClient();
data = await PeopleApi(httpClient!).people.connections.list(
'people/me',
personFields: 'names,addresses',
pageToken: nextPageToken,
pageSize: 100,
);
}

How to use Google API in flutter?

I want to use Google Cloud Natural Language in my Flutter app,I got Google API package
This works for flutter and theGoogle API_AUTH dependence is working for 0.2.1.
How do I implement them ?
This worked for me:
Logging in using package google_sign_in and then get auth headers from it:
import 'package:google_sign_in/google_sign_in.dart'
show GoogleSignIn, GoogleSignInAccount;
import 'package:googleapis/people/v1.dart'
show ListConnectionsResponse, PeopleApi;
useGoogleApi() async {
final _googleSignIn = new GoogleSignIn(
scopes: [
'email',
'https://www.googleapis.com/auth/contacts.readonly',
],
);
await _googleSignIn.signIn();
final authHeaders = _googleSignIn.currentUser.authHeaders;
// custom IOClient from below
final httpClient = GoogleHttpClient(authHeaders);
data = await PeopleApi(httpClient).people.connections.list(
'people/me',
personFields: 'names,addresses',
pageToken: nextPageToken,
pageSize: 100,
);
}
This is a custom IOClient implementation that automatically adds the auth headers to each request. The googleapis call support passing a custom HTTP client to be used instead of the default (see above)
import 'package:http/io_client.dart';
import 'package:http/http.dart';
class GoogleHttpClient extends IOClient {
Map<String, String> _headers;
GoogleHttpClient(this._headers) : super();
#override
Future<StreamedResponse> send(BaseRequest request) =>
super.send(request..headers.addAll(_headers));
#override
Future<Response> head(Object url, {Map<String, String> headers}) =>
super.head(url, headers: headers..addAll(_headers));
}
I can't add comments yet, so I'll just post it as an answer.
I kept trying to make a GoogleHttpClient as per the top answer, but on the import, it says "The library 'package:http/http.dart' doesn't export a member with the shown name 'IOClient'."
I found the answer here https://pub.dartlang.org/packages/http#-changelog-tab-, which says you should import IOClient separately as such: import 'package:http/io_client.dart';
I thought this might help out others who are new to flutter and its implementation of Google APIs.
The accepted answer is most likely written towards an older version of the SDK I just couldn't get it to work. This is what works for me as of now.
As an example, the following allow us to access files in Google Drive which is part of googleapis.
Dependencies
pubspec.yaml:
dependencies:
google_sign_in: any
googleapis: any
(I just put any here as a example, but you should specific the version(s) for you actual app.)
How it works
Necessary imports:
import 'package:googleapis/drive/v3.dart' as drive;
import 'package:google_sign_in/google_sign_in.dart' as signIn;
Step 1, sign in the user and ask for access permission (scope) to google drive:
final googleSignIn = signIn.GoogleSignIn.standard(scopes: [drive.DriveApi.DriveScope]);
final sign.GoogleSignInAccount account = await googleSignIn.signIn();
Step 2, build a AuthenticateClient:
class AuthenticateClient extends http.BaseClient {
final Map<String, String> headers;
final http.Client client;
AuthenticateClient(this.headers, this.client);
Future<http.StreamedResponse> send(http.BaseRequest request) {
return client.send(request..headers.addAll(headers));
}
}
As suggested in http, this is using the BaseClient with extra authentication headers (being composable).
Step 3, create a authenticated http client with from step 1 and 2 and access google drive API.
final baseClient = new Client();
final authenticateClient = AuthenticateClient(authHeader, baseClient);
final driveApi = drive.DriveApi(authenticateClient);
Checkout How to Use the Google Drive API With Flutter Apps for details.
Update to the accepted answer
Along with google_sign_in and googleapis packages, now you can use extension_google_sign_in_as_googleapis_auth package (provided by flutter.dev) to get configured http client. So the accepted answer can be simplified to below. No implementation of GoogleHttpClient is necessary.
import 'package:extension_google_sign_in_as_googleapis_auth/extension_google_sign_in_as_googleapis_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:googleapis/people/v1.dart';
useGoogleApi() async {
final _googleSignIn = new GoogleSignIn(
scopes: [
'email',
PeopleServiceApi.contactsReadonlyScope,
],
);
await _googleSignIn.signIn();
// custom IOClient
final httpClient = await _googleSignIn.authenticatedClient();
data = await PeopleApi(httpClient!).people.connections.list(
'people/me',
personFields: 'names,addresses',
pageToken: nextPageToken,
pageSize: 100,
);
}

Showing DropDown for Client sdk in swaggerUI

I am having my api documetation in swagger. I would like to provide my users with Client sdk dropdown with options of php and java. below is my code.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton(provider => Configuration);
services.AddTransient<IRegistrationRepository, ServiceUtilities>();
services.AddTransient<IClientServiceConnector, ClientServiceValidation>();
services.AddTransient<IEmailSender, EmailSender>();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
{
Title = "Onboarding API",
Version = "V1",
Description = "API to generate lead and return the url",
TermsOfService = "Please see terms and conditions",
Contact = new Swashbuckle.AspNetCore.Swagger.Contact {Name = "teggggrap",Email = "support#dd.com.au",Url= "https://www.dd.com.au/" }
});
var basePath = PlatformServices.Default.Application.ApplicationBasePath;
var xmlPath = Path.Combine(basePath, "gf.RegistrationApplication.xml");
c.IncludeXmlComments(xmlPath);
});
services.AddCors(options =>
{
options.AddPolicy("AllowAll", policy =>
{
policy.AllowAnyOrigin();
policy.AllowAnyHeader();
policy.AllowAnyMethod();
});
});
}
The consumers of your API can generate swagger-codegen to create clients for your API in their language of choice. You probably don't want to host this yourself, but you could give your users instructions to go to https://editor.swagger.io/ where they can upload your API spec and generate it from there.
I've generate my php and JS SDKs with Codegen. It's pretty easy to use and then you can push the folder to a public Github repo and from your Swagger UI, you can tell your consumers to visit and follow the Getting started section !
It generates README.md and docs for each model.
Here is my sdk

Get Error (error=access_denied) while logging in MVC5 application with facebook SDK

I have developed an application with ASP.NET MVC5. I have used Facebook external authentication in my application.
When I debug this application with the "Locallhost" domain, the Facebook login works well but when I publish the application in the main server,the AuthenticationManager.GetExternalLoginInfo() returns null and it gives me an error like this in the url:
http://xxxxx.com/Account/ExternalLoginCallback?ReturnUrl=%2Fen&error=access_denied#_=_
I have set the "Site URL" as "http://xxxx.com" and "Valid OAuth redirect URIs" as "http://xxxx.com/signin-facebook" in the Facebook development console.
My setting in the Startup.Outh.cs file is:
var FacebookOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions();
FacebookOptions.AppId = ConfigurationManager.AppSettings["Facebook_User_Key"];
FacebookOptions.AppSecret = ConfigurationManager.AppSettings["Facebook_Secret_Key"];
FacebookOptions.Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider()
{
OnAuthenticated = async context =>
{
context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));
foreach (var claim in context.User)
{
var claimType = string.Format("urn:facebook:{0}", claim.Key);
string claimValue = claim.Value.ToString();
if (!context.Identity.HasClaim(claimType, claimValue))
context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, "XmlSchemaString", "Facebook"));
}
}
};
FacebookOptions.SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie;
app.UseFacebookAuthentication(FacebookOptions);
I don't know why the external login does not work only in the server with my main domain name. please help me about this problem.
I encountered pretty much the same symptoms you describe:
shortly:
A Facebook authentication worked well on localhost, and after uploading the project to another server (and changing the site URL on Facebook console), authentication did not succeed.
I would recommend you roll back to the MVC template code, and if that works - notice any changes you have made to the middleware code (Startup.Auth.sc).
In particular pay attention to code that interacts with LOCAL configuration, such as Disk I/O and OS permissions for local services.
My particular case:
Starting from the Owin/Katana supported Visual Studio template of a WebAPI project, external login was working perfectly with Facebook, Microsoft and Google OAuth middleware, when testing on localhost.
Later I added come code to Startup.Auth.sc because I needed further authentication activity.
So this was the original code:
public void ConfigureAuth(IAppBuilder app)
{
// see WebAPI template of Visual Studio 2013/2015
...
app.UseFacebookAuthentication(
appId: 99999999,
appSecret: *******);
}
and this was replacement:
public void ConfigureAuth(IAppBuilder app)
{
// see WebAPI template of Visual Studio 2013/2015
...
app.UseFacebookAuthentication(GetFacebookAuth());
}
private FacebookAuthenticationOptions GetFacebookAuth()
{
string picRequest =
String.Format("/me/picture?redirect=false&width={0}&height={0}", ProfileInfoClaimsModel.PIC_SIDE_PX);
var facebookProvider = new FacebookAuthenticationProvider()
{
OnAuthenticated = async (context) =>
{
var client = new FacebookClient(context.AccessToken);
dynamic me = client.Get("/me?fields=id,name,locale");
dynamic mePicture = client.Get(picRequest);
// storing temporary social profile info TO A LOCAL FOLDER
// uploading the local folder to a service WITH A LOCAL CREDENTIAL FILE
...
}
};
var options = new FacebookAuthenticationOptions()
{
AppId = 0123456789,
AppSecret = ******,
Provider = facebookProvider,
};
return options;
}
You may notice that my comments will make the problem obvious - the code points to local resources.
Then I published the project to a virtual server (by Amazon EC2) running Windows Server 2012 with IIS 8.5.
From that moment I kept getting error=access_denied in the redirect from /signin-facebook.
I decided to follow this good old concept, and go back to the original template code. Pretty soon I figured out that I forgot to configure the new server. For instance, the folder the code refers to did not exist and the site had no permission to create it.
Obviously, that solved it.

Resources