/// <reference types="node" />
/// <reference types="qs" />
/// <reference types="range-parser" />

import { Request as AtlassianJwtRequest } from 'atlassian-jwt';
import { NextFunction, Request as ExpressRequest, Response as ExpressResponse } from 'express-serve-static-core';
import { JwtPayload } from 'jsonwebtoken';

export interface AtlassianConnectConfig {
	baseUrl: string;
}
export type TenantDataWithSharedSecret = {
	sharedSecret: string;
} & unknown;
export type TenantDataWithClientKey = {
	clientKey: string;
} & unknown;
export type TenantByClientKeySupplier = (clientKey: string) => Promise<TenantDataWithSharedSecret | null>;
export interface AtlassianConnectAuthenticationMiddlewareConfig {
	fetchTenantByClientKey: TenantByClientKeySupplier;
	requestsForQshValidation?: AtlassianJwtRequest[];
}
export type AuthenticatedInstallationRequest = ExpressRequest & {
	validatedJwtPayload: JwtPayload;
};
/**
 * Returns a middleware that can be used for authentication of install and uninstall lifecycle hook requests in Atlassian Connect ecosystem.
 * The composed middleware verifies the requests as outlined in the Atlassian Connect documentation using a asymmetric encryption and a RSA public key
 * provided from an Atlassian Host.
 *
 * @see https://community.developer.atlassian.com/t/action-required-atlassian-connect-installation-lifecycle-security-improvements/49046
 * @see https://developer.atlassian.com/cloud/confluence/understanding-jwt/
 *
 * You have to provide the baseUrl of your app. This is most probably the host you provide as a "baseUrl" in your atlassian-connect.json.
 *
 * Example usage:
 *
 * app.post('/lifecycle/installed/', [composeAtlassianConnectInstallationMiddleware({baseUrl: ATLASSIAN_CONNECT_FILE.baseUrl})], async (req: Request & ReqWithFirebaseUser, res: Response) => {
 *     console.log('Atlassian Connect Lifecycle Hook triggered: /installed', req.body);
 *     await persistInstallation(db, req.body);
 *     res.send();
 * });
 *
 * @param baseUrl
 * baseUrl from your atlassian-connect.json.
 */
export declare function composeAtlassianConnectInstallationMiddleware({ baseUrl }: AtlassianConnectConfig): (req: AuthenticatedInstallationRequest, res: ExpressResponse, next: NextFunction) => void;
export type AuthenticatedAtlassianRequest = ExpressRequest & {
	atlassianVerified: {
		userAccountId: string;
		clientKey: string;
		tenant: TenantDataWithSharedSecret;
		jwtPayload: JwtPayload;
	};
};
/**
 * Returns a middleware that can be used for authentication of user requests.
 * The composed middleware verifies the requests as outlined in the Atlassian Connect documentation using a JWT signed with the sharedSecret of a tenant.
 *
 * @see https://developer.atlassian.com/cloud/confluence/understanding-jwt/

 * @param baseUrl
 * BaseUrl from your atlassian-connect.json.
 * @param fetchTenantByClientKey
 * Method that asynchronously returns the data that you have stored for the tenant given its clientKey. Returned data has to contain at least a "sharedSecret".
 * Return null if no matching tenant can be found by your implementation.
 * @param requestsForQshValidation (optional)
 * The default behaviour of the returned middleware is to use the actual Express request that is passed into it to validate the given JWTs query hash (qsh claim).
 * You can optionally choose to validate the given qsh against another fictitious requests. If one request matches the qsh, the request is assumed to be authenticated.
 * This functionality can be used in combination with createJwtForRequestAuthorization which allows you to create JWTs for such fictitious requests.
 * A client can receive such JWTs and use it to make requests to endpoints protected by the returned middleware.
 *
 * @see create-jwt.ts for code examples
 */
export declare function composeAtlassianRequestAuthenticationMiddleware({ baseUrl, fetchTenantByClientKey, requestsForQshValidation }: AtlassianConnectConfig & AtlassianConnectAuthenticationMiddlewareConfig): (req: AuthenticatedAtlassianRequest, res: ExpressResponse, next: NextFunction) => void;
/**
 * Creates a JWT that can be used for authentication of requests by providing it in the Authorization header as "JWT xxx".
 * @param tenantData
 * Data object you have stored for the Atlassian tenant. It has to contain a sharedSecret (used for JWT signing) and a
 * clientKey (used as the JWT audience).
 * @param issuer
 * Issuer string to be passed as the JWTs iss claim. Should be set to the app-key if you use this token for api calls
 * in server-to-server communication with atlassian host products.
 * @param expirationInSeconds
 * JWT expiration time in seconds. defaults to 300.
 * @param method
 * HTTP method of the signed request (GET, POST, ...). defaults to GET.
 * @param pathname
 * Pathname of the signed request (sth. like "/rest/api/content"), used to generate query hash (qsh claim).
 * @param body
 * Body of the signed request, used to generate query hash (qsh claim).
 * @param query
 * Query params of the signed request, used to generate query hash (qsh claim).
 * @param baseUrl
 * BaseUrl of the requests. Gets passed as baseUrl param to Atlassians jwt library. Can be omitted if pathname is set correctly
 * @param additionalClaims
 * Additional claims to be appended to JWT payload. Can be used to override aspects of the JWT or to enrich it with additional context information like a userId
 *
 * @example
 * usage for api calls to confluence
 * ```ts
 * const jwt = createJwtForRequestAuthorization({
 *		issuer: "my-app-key",
 *		request: {pathname: "rest/api/content", method: "GET"},
 *		tenantData: {
 *			clientKey: "tenant-key-of-installation-cb1f7a7ee297",
 *			sharedSecret: "sharedSecretOfClientFromInstallationProcess"
 *		}
 *	});
 * ```
 *
 * @example
 * usage for authentication against middleware function from authenticate-middleware.ts with fictitious path
 * ```ts
 * // 1. generate jwt
 * const jwt = createJwtForRequestAuthorization({
 *		issuer: "tenant-key-of-installation-cb1f7a7ee297",
 *		request: {pathname: "/admin-only", method: "GET"},
 *		tenantData: {
 *			clientKey: "tenant-key",
 *			sharedSecret: "tenants-shared-secret"
 *		}
 *	});
 *
 * // ... pass it to the client ...
 *
 * // 2. validate with middleware
 * const middleware = composeAtlassianRequestAuthenticationMiddleware({
 *		baseUrl: "https://your.apps.base.url",
 *		fetchTenantByClientKey: (clientKey: string) => Promise.resolve({
 *			clientKey: "tenant-key",
 *			sharedSecret: "tenants-shared-secret"
 *		}),
 *		requestsForQshValidation: [{method: "GET", pathname: "/admin-only"}]
 *	});
 *
 * // 3. use middleware for authentication
 * app.post("/some/endpoint/", [middleware], async(req: Request, res: Response) => {
 *     res.send();
 * });
 * ```
 **/
export declare function createJwtForRequestAuthorization({ tenantData, issuer, expirationInSeconds, request: { method, pathname, body, query }, baseUrl, additionalClaims, }: CreateJwtForRequestParams): string;
export interface CreateJwtForRequestParams {
	tenantData: TenantDataWithSharedSecret & TenantDataWithClientKey;
	issuer: string;
	expirationInSeconds?: number;
	request: Partial<AtlassianJwtRequest>;
	baseUrl?: string;
	additionalClaims?: Partial<JwtPayload>;
}

export {};
