@Override protected ModelAndView handleRequestInternal( final HttpServletRequest request, final HttpServletResponse response) throws Exception { String accessToken = request.getParameter(OAuthConstants.ACCESS_TOKEN); if (StringUtils.isBlank(accessToken)) { final String authHeader = request.getHeader("Authorization"); if (StringUtils.isNotBlank(authHeader) && authHeader.toLowerCase().startsWith(OAuthConstants.BEARER_TOKEN.toLowerCase() + ' ')) { accessToken = authHeader.substring(OAuthConstants.BEARER_TOKEN.length() + 1); } } LOGGER.debug("{} : {}", OAuthConstants.ACCESS_TOKEN, accessToken); try (final JsonGenerator jsonGenerator = this.jsonFactory.createJsonGenerator(response.getWriter())) { response.setContentType("application/json"); // accessToken is required if (StringUtils.isBlank(accessToken)) { LOGGER.error("Missing {}", OAuthConstants.ACCESS_TOKEN); jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("error", OAuthConstants.MISSING_ACCESS_TOKEN); jsonGenerator.writeEndObject(); return null; } // get ticket granting ticket final TicketGrantingTicket ticketGrantingTicket = (TicketGrantingTicket) this.ticketRegistry.getTicket(accessToken); if (ticketGrantingTicket == null || ticketGrantingTicket.isExpired()) { LOGGER.error("expired accessToken : {}", accessToken); jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("error", OAuthConstants.EXPIRED_ACCESS_TOKEN); jsonGenerator.writeEndObject(); return null; } // generate profile : identifier + attributes final Principal principal = ticketGrantingTicket.getAuthentication().getPrincipal(); jsonGenerator.writeStartObject(); jsonGenerator.writeStringField(ID, principal.getId()); jsonGenerator.writeObjectFieldStart(ATTRIBUTES); final Map<String, Object> attributes = principal.getAttributes(); for (final Map.Entry<String, Object> entry : attributes.entrySet()) { // jsonGenerator.writeStartObject(); jsonGenerator.writeObjectField(entry.getKey(), entry.getValue()); // jsonGenerator.writeEndObject(); } // jsonGenerator.writeEndArray(); jsonGenerator.writeEndObject(); return null; } finally { response.flushBuffer(); } }
private JSONObject createJSONPrinciple(Authentication auth) { Principal principal = auth.getPrincipal(); JSONObject principle = new JSONObject(); principle.put("id", principal.getId()); JSONArray jsonResult = new JSONArray(); for (Map.Entry<String, Object> entry : principal.getAttributes().entrySet()) { JSONObject attribute = new JSONObject(); attribute.put(entry.getKey(), entry.getValue()); jsonResult.add(attribute); } principle.put("attributes", jsonResult); return principle; }
/** * Gets sso sessions. * * @param option the option * @return the sso sessions */ private Collection<Map<String, Object>> getActiveSsoSessions( final SsoSessionReportOptions option) { final Collection<Map<String, Object>> activeSessions = new ArrayList<>(); final ISOStandardDateFormat dateFormat = new ISOStandardDateFormat(); for (final Ticket ticket : getNonExpiredTicketGrantingTickets()) { final TicketGrantingTicket tgt = (TicketGrantingTicket) ticket; if (option == SsoSessionReportOptions.DIRECT && tgt.getProxiedBy() != null) { continue; } final Authentication authentication = tgt.getAuthentication(); final Principal principal = authentication.getPrincipal(); final Map<String, Object> sso = new HashMap<>(SsoSessionAttributeKeys.values().length); sso.put(SsoSessionAttributeKeys.AUTHENTICATED_PRINCIPAL.toString(), principal.getId()); sso.put( SsoSessionAttributeKeys.AUTHENTICATION_DATE.toString(), authentication.getAuthenticationDate()); sso.put( SsoSessionAttributeKeys.AUTHENTICATION_DATE_FORMATTED.toString(), dateFormat.format(authentication.getAuthenticationDate())); sso.put(SsoSessionAttributeKeys.NUMBER_OF_USES.toString(), tgt.getCountOfUses()); sso.put(SsoSessionAttributeKeys.TICKET_GRANTING_TICKET.toString(), tgt.getId()); sso.put(SsoSessionAttributeKeys.PRINCIPAL_ATTRIBUTES.toString(), principal.getAttributes()); sso.put( SsoSessionAttributeKeys.AUTHENTICATION_ATTRIBUTES.toString(), authentication.getAttributes()); if (option != SsoSessionReportOptions.DIRECT) { if (tgt.getProxiedBy() != null) { sso.put(SsoSessionAttributeKeys.IS_PROXIED.toString(), Boolean.TRUE); sso.put(SsoSessionAttributeKeys.PROXIED_BY.toString(), tgt.getProxiedBy().getId()); } else { sso.put(SsoSessionAttributeKeys.IS_PROXIED.toString(), Boolean.FALSE); } } sso.put(SsoSessionAttributeKeys.AUTHENTICATED_SERVICES.toString(), tgt.getServices()); activeSessions.add(sso); } return activeSessions; }
/** * Determines the principal id to use for a {@link RegisteredService} using the following rules: * * <ul> * <li>If the service is marked to allow anonymous access, a persistent id is returned. * <li>If the {@link org.jasig.cas.services.RegisteredService#getUsernameAttribute()} is blank, * then the default principal id is returned. * <li>If the username attribute is available as part of the principal's attributes, the * corresponding attribute value will be returned. * <li>Otherwise, the default principal's id is returned as the username attribute with an * additional warning. * </ul> * * @param principal The principal object to be validated and constructed * @param registeredService Requesting service for which a principal is being validated. * @param serviceTicket An instance of the service ticket used for validation * @return The principal id to use for the requesting registered service */ private String determinePrincipalIdForRegisteredService( final Principal principal, final RegisteredService registeredService, final ServiceTicket serviceTicket) { String principalId = null; final String serviceUsernameAttribute = registeredService.getUsernameAttribute(); if (registeredService.isAnonymousAccess()) { principalId = this.persistentIdGenerator.generate(principal, serviceTicket.getService()); } else if (StringUtils.isBlank(serviceUsernameAttribute)) { principalId = principal.getId(); } else { if (principal.getAttributes().containsKey(serviceUsernameAttribute)) { principalId = principal.getAttributes().get(serviceUsernameAttribute).toString(); } else { principalId = principal.getId(); final Object[] errorLogParameters = new Object[] { principalId, registeredService.getUsernameAttribute(), principal.getAttributes(), registeredService.getServiceId(), principalId }; logger.warn( "Principal [{}] did not have attribute [{}] among attributes [{}] so CAS cannot " + "provide on the validation response the user attribute the registered service [{}] expects. " + "CAS will instead return the default username attribute [{}]", errorLogParameters); } } logger.debug( "Principal id to return for service [{}] is [{}]. The default principal id is [{}].", new Object[] {registeredService.getName(), principal.getId(), principalId}); return principalId; }
@Audit( action = "SERVICE_TICKET", actionResolverName = "GRANT_SERVICE_TICKET_RESOLVER", resourceResolverName = "GRANT_SERVICE_TICKET_RESOURCE_RESOLVER") @Timed(name = "GRANT_SERVICE_TICKET_TIMER") @Metered(name = "GRANT_SERVICE_TICKET_METER") @Counted(name = "GRANT_SERVICE_TICKET_COUNTER", monotonic = true) @Transactional(readOnly = false) @Override public ServiceTicket grantServiceTicket( final String ticketGrantingTicketId, final Service service, final Credential... credentials) throws AuthenticationException, TicketException { final TicketGrantingTicket ticketGrantingTicket = getTicket(ticketGrantingTicketId, TicketGrantingTicket.class); final RegisteredService registeredService = this.servicesManager.findServiceBy(service); verifyRegisteredServiceProperties(registeredService, service); final Set<Credential> sanitizedCredentials = sanitizeCredentials(credentials); Authentication currentAuthentication = null; if (sanitizedCredentials.size() > 0) { currentAuthentication = this.authenticationManager.authenticate( sanitizedCredentials.toArray(new Credential[] {})); final Authentication original = ticketGrantingTicket.getAuthentication(); if (!currentAuthentication.getPrincipal().equals(original.getPrincipal())) { throw new MixedPrincipalException( currentAuthentication, currentAuthentication.getPrincipal(), original.getPrincipal()); } ticketGrantingTicket.getSupplementalAuthentications().add(currentAuthentication); } if (currentAuthentication == null && !registeredService.getAccessStrategy().isServiceAccessAllowedForSso()) { logger.warn("ServiceManagement: Service [{}] is not allowed to use SSO.", service.getId()); throw new UnauthorizedSsoServiceException(); } final Service proxiedBy = ticketGrantingTicket.getProxiedBy(); if (proxiedBy != null) { logger.debug( "TGT is proxied by [{}]. Locating proxy service in registry...", proxiedBy.getId()); final RegisteredService proxyingService = servicesManager.findServiceBy(proxiedBy); if (proxyingService != null) { logger.debug("Located proxying service [{}] in the service registry", proxyingService); if (!proxyingService.getProxyPolicy().isAllowedToProxy()) { logger.warn( "Found proxying service {}, but it is not authorized to fulfill the proxy attempt made by {}", proxyingService.getId(), service.getId()); throw new UnauthorizedProxyingException( "Proxying is not allowed for registered service " + registeredService.getId()); } } else { logger.warn( "No proxying service found. Proxy attempt by service [{}] (registered service [{}]) is not allowed.", service.getId(), registeredService.getId()); throw new UnauthorizedProxyingException( "Proxying is not allowed for registered service " + registeredService.getId()); } } else { logger.trace("TGT is not proxied by another service"); } // Perform security policy check by getting the authentication that satisfies the configured // policy // This throws if no suitable policy is found getAuthenticationSatisfiedByPolicy( ticketGrantingTicket, new ServiceContext(service, registeredService)); final List<Authentication> authentications = ticketGrantingTicket.getChainedAuthentications(); final Principal principal = authentications.get(authentications.size() - 1).getPrincipal(); final Map<String, Object> principalAttrs = registeredService.getAttributeReleasePolicy().getAttributes(principal); if (!registeredService .getAccessStrategy() .doPrincipalAttributesAllowServiceAccess(principalAttrs)) { logger.warn( "ServiceManagement: Cannot grant service ticket because Service [{}] is not authorized for use by [{}].", service.getId(), principal); throw new UnauthorizedServiceForPrincipalException(); } final String uniqueTicketIdGenKey = service.getClass().getName(); logger.debug("Looking up service ticket id generator for [{}]", uniqueTicketIdGenKey); UniqueTicketIdGenerator serviceTicketUniqueTicketIdGenerator = this.uniqueTicketIdGeneratorsForService.get(uniqueTicketIdGenKey); if (serviceTicketUniqueTicketIdGenerator == null) { serviceTicketUniqueTicketIdGenerator = this.defaultServiceTicketIdGenerator; logger.debug( "Service ticket id generator not found for [{}]. Using the default generator...", uniqueTicketIdGenKey); } final String ticketPrefix = authentications.size() == 1 ? ServiceTicket.PREFIX : ServiceTicket.PROXY_TICKET_PREFIX; final String ticketId = serviceTicketUniqueTicketIdGenerator.getNewTicketId(ticketPrefix); final ServiceTicket serviceTicket = ticketGrantingTicket.grantServiceTicket( ticketId, service, this.serviceTicketExpirationPolicy, currentAuthentication != null); this.serviceTicketRegistry.addTicket(serviceTicket); logger.info( "Granted ticket [{}] for service [{}] for user [{}]", serviceTicket.getId(), service.getId(), principal.getId()); return serviceTicket; }