concourse: cf-resource sso login options - concourse

How to configure cf resource with sso options ?
Is there any way that we can pass the passcode url to obtain the token through cf resource and pass it as an --sso-passcode for login?
- name: cf
type: cf
source:
api: ((cloud_foundry_api))
username: ((cloud_foundry_username))
password: ((cloud_foundry_password))
organization: ((cloud_foundry_organization))
space: ((cloud_foundry_space))

Related

APEX and Keycloak integration - redirect problem after login

I'm trying to upgrade my APEX application (APEX 20.2.0.00.20) with a Keycloak authorization procedure.
What I am doing:
A - On Keycloak:
Realm: we already have a realm configured, which is used by other apps, in other development technologies.
1 - Client configuration - first attempt:
Root URL: ${authBaseUrl}
Valid Redirect URIs: /realms/[realm]/[client]/*
Base URL: /realms/[realm]/[client]/
Web Origins: *
2 - Client configuration - second attempt:
Root URL: empty
Valid Redirect URIs: http://[APEX app IP]:7020/*
Base URL: http://[APEX app IP]:7020/ords/[workspace]/r/[app_name]/
Web Origins: *
APEX configuration:
Authentication Scheme:
Credential Store: [APEX webcredential configured to keycloak client]
Authentication Provider: generic oauth2 provider.
Authorization Endpoint URL:
https://[keycloak address]/auth/realms/[realm]/protocol/openid-connect/auth
Token Endpoint URL:
https://[keycloak address]/auth/realms/[realm]/protocol/openid-connect/token
User Info Endpoint URL:
https://[keycloak address]/auth/realms/[realm]/protocol/openid-connect/userinfo
Token Authentication Method: basic authentication and client id in body
Scope: email
Authentication URI Parameters: empty
Username: #sub# (#APEX_AUTH_NAME#)
Convert Username To Upper Case: no
Verify Attributes: yes
** Tests **
I run my APEX app URL in workspace.
Test result of Client configuration nr. 1:
The following URL is shown as result:
https://[keycloak host]/auth/realms/[realm]/protocol/openid-connect/auth?response_type=code&client_id=[client_name]&scope=email&redirect_uri=http://[APEX address]:7020/ords/apex_authentication.callback&state=[A TOKEN/HASH]
And on the screen, the keycloak background image with the message:
Invalid parameter: redirect_uri. and a return to application link.
Test result of Client configuration nr. 2:
The keycloak login URL is activated and the login form is shown.
I type my user and password (keycloak user, configured on the client) and submit.
The following URL is shown as result:
https://[keycloak host]:7020/ords/apex_authentication.callback?state=[A TOKEN/HASH]
And on the screen, a APEX grey background (I know is a apex screen because a error with the icon is shown here) with the message:
Error processing request.
Contact your application administrator.
Question:
I think the second configuration is better, because I can do the Login on keycloak, but the redirect by keycloak to APEX fails, I think I APEX side.
Maybe any information sent by keycloak is wrong or it is missed.
Anyone knows what is the right configuration in APEX and keycloak?

Additional claims not showing up on cognito ID token

I am using a following CloudFormention Template to add cognito:preferred_role claim to my ID token.
IdentityPoolRoleAttachment:
Type: AWS::Cognito::IdentityPoolRoleAttachment
Properties:
IdentityPoolId: !Ref IdentityPool
Roles:
"authenticated": !GetAtt AuthenticatedRole.Arn
"unauthenticated": !GetAtt UnAuthenticatedRole.Arn
RoleMappings:
 "userpool1":
IdentityProvider: !Join …
AmbiguousRoleResolution: Deny
Type: Token
But I recieved an ID token only contains standard claims on my client app.
I also noticed unauthenticated role is applyed to a user after login.
I changed AmbiguousRoleResolution to AuthenticatedRole but still no additional claims.
What I am missing to do?
I need to send this token to an api gateway to assume role base on cognito:roles or cognito:preferred_role claim to call dynamo sdk using authenticated role on lambda.

How to make tokenUrl configurable

Is there anyway to make the token url in OpenAPI spec configurable.
For instance the I want to make the realm {{REALM_NAME_HERE}} below configurable from swagger UI.
securitySchemes:
oauth:
type: oauth2
description: This API uses OAuth 2
flows:
clientCredentials:
tokenUrl: http://localhost:32777/auth/realms/{{REALM_NAME}}/protocol/openid-connect/token
scopes: {}
tokenUrl does not support variables. There's a corresponding feature request in the OpenAPI Specification repository:
https://github.com/OAI/OpenAPI-Specification/issues/551
However, if the parameterized part of the tokenUrl (in your example - http://localhost:32777/auth/realms/{{REALM_NAME}}) also happens to be the API server URL, you can define tokenUrl relative to the server URL:
openapi: 3.0.0
servers:
- url: 'http://localhost:32777/auth/realms/{REALM_NAME}'
variables:
REALM_NAME:
default: some_default_realm # default value is required
paths:
...
components:
securitySchemes:
oauth:
type: oauth2
description: This API uses OAuth 2
flows:
clientCredentials:
tokenUrl: './protocol/openid-connect/token'
scopes: {}

Restrict API access to specific app clients

I have built an iOS and an Android app. These apps use Cognito User Pools to allow public authenticated and unauthenticated access to API Gateway.
I am trying to prevent third-party apps from accessing this API. I only want apps that I have authorized to have API access. Is possible to limit access to APIG to only my apps?
Cognito provides the notion of an App Client ID and App Client Secret in the settings for the user pool. Is this the preferred mechanism to limit Cognito logins to whitelisted clients/apps? The docs provide little clarification as to the purpose of this configuration or a best practice for keeping these keys secure in the wild.
Are there alternative methods to achieve what I'm attempting? Is this goal even possible to accomplish? I believe an app could be reverse engineered for these keys or they could be discovered via a network sniffer.
I am a bit of a novice on API security so your insights are appreciated.
Have a look at Cognito Identity. Cognito Federated Identity Pools provide for both authenticated & unauthenticated access. This is going to be long, so please bear with me. (my code examples are using cloudformation in yaml or JS). I will assume that you have created your user pool & app client. You are going to need those to create an identity pool. I will also assume that your user pool allowed oauth flows is set to implicit grant and allowed oauth scope is openid. This is required to get the id_token which is used to create a federated identity.
create cognito identity pool using your cognito user pool as an authenticated provider. Sample CFN yaml for the same
AccIdenAdminPool:
Type: "AWS::Cognito::IdentityPool"
Properties:
IdentityPoolName: <identity pool name as input>
AllowUnauthenticatedIdentities: true
CognitoIdentityProviders:
- ClientId: <your app client id>
ProviderName: "cognito-idp.us-east-1.amazonaws.com/<your user pool id>"
ServerSideTokenCheck: true
Now attach your authenticated & unauthenticated roles to the identity pool you just created. Sample JS code -
module.exports.attachRole = (event, context, callback) => {
console.log(JSON.stringify(event)); // successful response
let params = {
IdentityPoolId: event.identityPoolId, /* required */
Roles: {
/* required */
'authenticated': <auth role arn>,
'unauthenticated': <unauth role arn>
},
};
cognitoidentity.setIdentityPoolRoles(params, function (err, data) {
if (err) {
console.log(err, err.stack);
}
else {
console.log("success"); // successful response
}
});
}
Change API gateway authentication from Cognito user pool authorizer to AWS_IAM. This is a must. If for some reason you cannot do this, you need to figure some other way out to have closed unauthenticated access to you APIs.
For authenticated access, use the id_token (received after successful login), identity pool id & user pool id to get CognitoIdentityCredentials. Sample code -
function getAccessToken(idToken, idenPoolId, userPool) {
let region = idenPoolId.split(":")[0];
let provider = "cognito-idp." + region + ".amazonaws.com/" + userPool;
let login = {};
login[provider] = idToken;
console.log(provider + ' || ' + idenPoolId);
// Add the User's Id Token to the Cognito credentials login map.
let credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: idenPoolId,
Logins: login
});
//call refresh method in order to authenticate user and get new temp credentials
credentials.get((error) => {
if (error) {
console.error(error);
} else {
console.log('Successfully logged!');
console.log('AKI:'+ credentials.accessKeyId);
console.log('AKS:'+ credentials.secretAccessKey);
console.log('token:' + credentials.sessionToken);
}
});
}
Use this access key,secret keyandtoken` to hit your APIs. It will have permissions based on your authenticated role you provisioned in step 2.
For unauthenticated access, login step will obviously be skipped but you can still generate temporary keys for access to your APIs. Sample code is very similar, with one key difference. Logins parameter is not required.
function getUnauthToken(idenPoolId) {
console.log(idenPoolId);
// Add the User's Id Token to the Cognito credentials login map.
let credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: idenPoolId,
});
credentials.get((error) => {
if (error) {
console.error(error);
} else {
console.log('Unauth AKI:'+ credentials.accessKeyId);
console.log('Unauth AKS:'+ credentials.secretAccessKey);
console.log('Unauth token:' + credentials.sessionToken);
}
});
}
This set of keys has permissions based on your unauthenticated role as provisioned in step 2.
Roles - this is how created roles & it's policy for my API gateway. Example in CFN yaml
AuthenticatedRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: "AuthenticatedRole"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "sts:AssumeRoleWithWebIdentity"
Principal:
Federated:
- "cognito-identity.amazonaws.com"
Condition:
StringEquals:
cognito-identity.amazonaws.com:aud: <your identity pool id>
ForAnyValue:StringLike:
cognito-identity.amazonaws.com:amr: authenticated
Path: "/"
AuthRolePolicy:
Type: "AWS::IAM::Policy"
Properties:
PolicyName: AuthRolePolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action: "execute-api:Invoke"
Resource:
- "arn:aws:execute-api:<region>:<account id>:<api id>/*/*/acc/*"]]
Roles:
-
Ref: AuthenticatedRole
UnauthRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: UnauthRole
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "sts:AssumeRoleWithWebIdentity"
Principal:
Federated:
- "cognito-identity.amazonaws.com"
Condition:
StringEquals:
cognito-identity.amazonaws.com:aud: <your identity pool id>
Path: "/"
UnauthRolePolicy:
Type: "AWS::IAM::Policy"
Properties:
PolicyName: UnauthRolePolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action: "execute-api:Invoke"
Resource:
- "arn:aws:execute-api:<region>:<account id>:<api id>/*/GET"/acc/dept/12/*"]]
Roles:
-
Ref: UnauthRole
So based on above roles I have different access for my authenticated & unauthenticated users. Only caveat here is that your identity pool id must be a secret (i.e. not a good thing to expose in the browser).
Hope this helps.

Error in implementing OAuth2 for Swagger Documentation of an API

I have the following code in:
/oauth2/gARD:
get:
tags:
- RM API
summary: Fecthes as per user's request.
operationId: gARD
security:
- OAuth2: [read]
consumes:
- application/json
produces:
- application/json
parameters:
- in: header
name: token
description: Authorization
type: string
required: true
responses:
'200':
description: Successful
'500':
description: Returns error message
And I have the following in the components category below the above code:
components:
securitySchemes:
OAuth2:
type: oauth2
flow:
authorizationCode:
authorizationUrl: https://example.com/oauth/authorize
tokenUrl: https://example.com/oauth/token
scopes:
read: Grants read access
write: Grants write access
admin: Grants access to admin operations
Everything's referenced from this link. I am getting "Security requirements must match a security definition" error.
You are mixing OpenAPI 2.0 and 3.0 syntax. components.securitySchemes is OpenAPI 3.0 syntax, but your path definition uses 2.0 syntax.
Assuming you use OpenAPI 2.0, the security definition should look like:
securityDefinitions:
OAuth2:
type: oauth2
flow: accessCode
authorizationUrl: https://example.com/oauth/authorize
tokenUrl: https://example.com/oauth/token
scopes:
read: Grants read access
write: Grants write access
admin: Grants access to admin operations