JWT Integration
Mission apps are expected to use the Platform One Keycloak integration for their applications rather than standing up their own Keycloak private servers. The Platform One Keycloak is a layer abstracted in front of applications that is automatically integrated into every mission app. This means that no actions need to be performed to integrate with Keycloak from a development perspective. This means that Platform One and Party Bus have control over Keycloak and the addition of any users that may need to authenticate to mission applications. Therefore, if your application needs to expand its user base, then you will need to create tickets for login.dso.mil onboarding.
Additionally, login.dso.mil does not contain any public clients. Therefore, in order to connect, the client secret and client id must be known. We do not offer this information to customers as it is sensitive and there are no or few use cases where connecting directly to the client is necessary.
However, there is the question of being able to authorize users and control RBAC within an application. This can be done by parsing JWT headers. Specifically the Authorization request header. Information on this can be found below.
UG - AuthService/JWT - Django Implementation
WIDOW utilizes Django as its backend for the REST API. For the backend we need to associate each users request with their action, so a mission commander can have an active view of what is changed for a mission.
By utilizing the authorization service we can guarantee everyone accessing the backend has been authenticated through the Platform One SSO.
Decode the JWT for User Information
The approved way of receiving the user information is to decode the JWT that is passed through the Authorization header.
For Django/Python, we leverage PyJWT library.
JWT Decode Example:
def decode_jwt(request):
encoded_auth_header = request.headers["Authorization"]
auth_header = jwt.decode(encoded_auth_header.split("Bearer ")[1], verify=False)
return auth_header
class PlatformOneAuthentication(authentication.BaseAuthentication):
def authenticate(self, request):
username = "AnonymousUser" # Default user
if "Authorization" in request.headers:
jwt_decoded = decode_jwt(request)
username = jwt_decoded["preferred_username"]
user = User.objects.get_or_create(username=username)[0]
2
3
4
5
6
7
8
9
10
11
12
Example JWT
The following JWT is passed in the Authorization header:
eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0Q0s2OWJXNjZIRTJ3cGg5VnVCczBmVGMxTWFFVFNUcFUxaWZsRWtCSFI0In0.eyJleHAiOjE2MDAzMDkzMjYsImlhdCI6MTYwMDMwODQyNiwiYXV0aF90aW1lIjoxNjAwMzA4NDI2LCJqdGkiOiI0YzEyNzU5My01MzQzLTQ1MTctYTdjMS00M2UxZWY4MTk5OTIiLCJpc3MiOiJodHRwczovL2xvZ2luLmRzb3AuaW8vYXV0aC9yZWFsbXMvYmFieS15b2RhIiwiYXVkIjoiaWw0XzE5MWY4MzZiLWVjNTAtNDgxOS1iYTEwLTFhZmFhNWI5OTYwMF9taXNzaW9uLXdpZG93Iiwic3ViIjoiMGIwOTIzNTItNDhlZS00NzY1LTgyZTYtOTc1Y2I0NWFmMmU3IiwidHlwIjoiSUQiLCJhenAiOiJpbDRfMTkxZjgzNmItZWM1MC00ODE5LWJhMTAtMWFmYWE1Yjk5NjAwX21pc3Npb24td2lkb3ciLCJub25jZSI6ImIyYXlWbFlTd1I0NlJhcGV1Z1RqTjF5MUJRdHdrZ3YxdmNLeWVOaFNVLVUiLCJzZXNzaW9uX3N0YXRlIjoiMWJhZWQ4NzMtYjRjZi00ZTQzLWFiOWItN2JiNjkyNzA0MWNhIiwiYWNyIjoiMSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJncm91cC1zaW1wbGUiOlsiSW1wYWN0IExldmVsIDIgQXV0aG9yaXplZCIsIkltcGFjdCBMZXZlbCA0IEF1dGhvcml6ZWQiLCJJbXBhY3QgTGV2ZWwgNSBBdXRob3JpemVkIiwiVGVzdGVycyIsIldpZG93IiwiV2lkb3ciXSwicHJlZmVycmVkX3VzZXJuYW1lIjoibWF0dC5zaGF2ZXIiLCJnaXZlbl9uYW1lIjoiTWF0dGhldyIsImFjdGl2ZWNhYyI6IiIsImFmZmlsaWF0aW9uIjoiQ29udHJhY3RvciIsImdyb3VwLWZ1bGwiOlsiL0ltcGFjdCBMZXZlbCAyIEF1dGhvcml6ZWQiLCIvSW1wYWN0IExldmVsIDQgQXV0aG9yaXplZCIsIi9JbXBhY3QgTGV2ZWwgNSBBdXRob3JpemVkIiwiL1BsYXRmb3JtIE9uZS9UZXN0ZXJzIiwiL1BsYXRmb3JtIE9uZS9Qcm9kdWN0cy9XaWRvdyIsIi9Qcm9kdWN0LVRlYW1zL1dpZG93Il0sIm9yZ2FuaXphdGlvbiI6IkJyYWluR3UiLCJuYW1lIjoiTWF0dGhldyBTaGF2ZXIiLCJ1c2VyY2VydGlmaWNhdGUiOiJTSEFWRVIuTUFUVEhFVy5USE9NQVMuMTUxODA1Mzk0NSIsInJhbmsiOiJOL0EiLCJmYW1pbHlfbmFtZSI6IlNoYXZlciIsImVtYWlsIjoibWF0dEBicmFpbmd1LmNvbSJ9.EoaCJd9pcFO9W7VCtJ8D_nvSDCn8uSJAdj3WVWza7WXEWURk8EnwNf3m7ECUH3FG9LAH8AxA8nkTJIGmOpDg3IQ0s1PK_1wfG08zPlvMB8Hzvjw8N-LWTFMn-hcMtC0B4L0LdmTmrAzEBtB-KppBp_xpT1wvzcxCixjBNAGN6jYD1-cMnvcDifB2pEqy6xb40pgRlY5B8PufxJF6c7om1TEE2DiT_C4qNlRNUbob7T8qaGab5CvwMO8Og7yUInv6bKXonmgUCEKjWnj7rawjoliuL8kKF5q7P3_0KE4SqHnq_0GQLS9YlRCXAF_6TH9SLB0R12FV_aYbTS6U_vkmog
Example Decoded JWT
After decoding the JWT, you will receive the following:
NOTE
The rank and affiliation fields are optional; if they are not provided, the keys will not exist.
Header
{
"alg": "RS256",
"typ": "JWT",
"kid": "4CK69bW66HE2wph9VuBs0fTc1MaETSTpU1iflEkBHR4"
}
Payload (with CAC)
{
"exp": 1625602142,
"iat": 1625601242,
"auth_time": 1625601242,
"jti": "a92695fd-9342-4810-bcc2-057af6dc45d4",
"iss": "https://login.dso.mil/auth/realms/baby-yoda",
"aud": "il2-staging_7a5a0fb5-bd49-49b0-a441-fa6092696c3a_mission-il2-staging-general",
"sub": "a42b83c9-6991-4c7d-9a04-4de00dd527e9",
"typ": "ID",
"azp": "il2-staging_7a5a0fb5-bd49-49b0-a441-fa6092696c3a_mission-il2-staging-general",
"nonce": "LguJO2WXZeaWtxP4Xquqb7EKWLtZJj2tU9xL4M13-6U",
"session_state": "0ff7a609-55f9-4d6e-844c-9c120d7b3a9d",
"at_hash": "546JFfg7sbTAeB7BkDZE4w",
"acr": "1",
"email_verified": true,
"group-simple": [
"Impact Level 2 Authorized",
"Impact Level 4 Authorized",
"Impact Level 5 Authorized"
],
"preferred_username": "jdoe",
"given_name": "John",
"activecac": "DOE.JOHN.1234567890",
"affiliation": "Other",
"group-full": [
"/Impact Level 2 Authorized",
"/Impact Level 4 Authorized",
"/Impact Level 5 Authorized"
],
"organization": "Company, Inc",
"name": "John Doe",
"usercertificate": "DOE.JOHN.1234567890",
"rank": "N/A",
"family_name": "Doe",
"email": "john@company.com"
}
Payload (without CAC):
{
"exp": 1625603848,
"iat": 1625602948,
"auth_time": 1625602948,
"jti": "df0ddf45-a8bc-4db9-aea9-6c891ef9698d",
"iss": "https://login.dso.mil/auth/realms/baby-yoda",
"aud": "il2-staging_7a5a0fb5-bd49-49b0-a441-fa6092696c3a_mission-il2-staging-general",
"sub": "631794f1-54b6-45bd-bba9-3632a21abb07",
"typ": "ID",
"azp": "il2-staging_7a5a0fb5-bd49-49b0-a441-fa6092696c3a_mission-il2-staging-general",
"nonce": "VsRdnaoAw71t8PPRh6Gggy9wtkXUBWHOIIhC9y3sxSw",
"session_state": "9a416749-01aa-4c44-b33e-432088aedaed",
"at_hash": "5NNTMQbyn9jc_833Cuyf7Q",
"acr": "1",
"email_verified": true,
"group-simple": ["App"],
"affiliation": "Contractor",
"group-full": ["/Product-Teams/App"],
"organization": "Company, Inc.",
"name": "John Doe",
"rank": "N/A",
"preferred_username": "jdoe",
"given_name": "John",
"family_name": "Doe",
"email": "john@company.com",
"activecac": ""
}