Generating token using keycloak
[nonrtric/plt/sme.git] / capifcore / internal / securityservice / security.go
index ab0abde..dcf1dbb 100644 (file)
@@ -30,53 +30,71 @@ import (
        securityapi "oransc.org/nonrtric/capifcore/internal/securityapi"
 
        "oransc.org/nonrtric/capifcore/internal/invokermanagement"
+       "oransc.org/nonrtric/capifcore/internal/keycloak"
        "oransc.org/nonrtric/capifcore/internal/providermanagement"
        "oransc.org/nonrtric/capifcore/internal/publishservice"
 )
 
 type Security struct {
        serviceRegister providermanagement.ServiceRegister
-       apiRegister     publishservice.APIRegister
+       publishRegister publishservice.PublishRegister
        invokerRegister invokermanagement.InvokerRegister
+       keycloak        keycloak.AccessManagement
 }
 
-func NewSecurity(serviceRegister providermanagement.ServiceRegister, apiRegister publishservice.APIRegister, invokerRegister invokermanagement.InvokerRegister) *Security {
+func NewSecurity(serviceRegister providermanagement.ServiceRegister, publishRegister publishservice.PublishRegister, invokerRegister invokermanagement.InvokerRegister, km keycloak.AccessManagement) *Security {
        return &Security{
                serviceRegister: serviceRegister,
-               apiRegister:     apiRegister,
+               publishRegister: publishRegister,
                invokerRegister: invokerRegister,
+               keycloak:        km,
        }
 }
 
 func (s *Security) PostSecuritiesSecurityIdToken(ctx echo.Context, securityId string) error {
-       clientId := ctx.FormValue("client_id")
-       clientSecret := ctx.FormValue("client_secret")
-       scope := ctx.FormValue("scope")
+       var accessTokenReq securityapi.AccessTokenReq
+       accessTokenReq.GetAccessTokenReq(ctx)
 
-       if !s.invokerRegister.IsInvokerRegistered(clientId) {
-               return sendCoreError(ctx, http.StatusBadRequest, "Invoker not registered")
+       if valid, err := accessTokenReq.Validate(); !valid {
+               return ctx.JSON(http.StatusBadRequest, err)
        }
-       if !s.invokerRegister.VerifyInvokerSecret(clientId, clientSecret) {
-               return sendCoreError(ctx, http.StatusBadRequest, "Invoker secret not valid")
+
+       if !s.invokerRegister.IsInvokerRegistered(accessTokenReq.ClientId) {
+               return sendAccessTokenError(ctx, http.StatusBadRequest, securityapi.AccessTokenErrErrorInvalidClient, "Invoker not registered")
        }
-       if scope != "" {
-               scopeData := strings.Split(strings.Split(scope, "#")[1], ":")
-               if !s.serviceRegister.IsFunctionRegistered(scopeData[0]) {
-                       return sendCoreError(ctx, http.StatusBadRequest, "Function not registered")
-               }
-               if !s.apiRegister.IsAPIRegistered(scopeData[0], scopeData[1]) {
-                       return sendCoreError(ctx, http.StatusBadRequest, "API not published")
+
+       if !s.invokerRegister.VerifyInvokerSecret(accessTokenReq.ClientId, *accessTokenReq.ClientSecret) {
+               return sendAccessTokenError(ctx, http.StatusBadRequest, securityapi.AccessTokenErrErrorUnauthorizedClient, "Invoker secret not valid")
+       }
+
+       if accessTokenReq.Scope != nil && *accessTokenReq.Scope != "" {
+               scope := strings.Split(*accessTokenReq.Scope, "#")
+               aefList := strings.Split(scope[1], ";")
+               for _, aef := range aefList {
+                       apiList := strings.Split(aef, ":")
+                       if !s.serviceRegister.IsFunctionRegistered(apiList[0]) {
+                               return sendAccessTokenError(ctx, http.StatusBadRequest, securityapi.AccessTokenErrErrorInvalidScope, "AEF Function not registered")
+                       }
+                       for _, api := range strings.Split(apiList[1], ",") {
+                               if !s.publishRegister.IsAPIPublished(apiList[0], api) {
+                                       return sendAccessTokenError(ctx, http.StatusBadRequest, securityapi.AccessTokenErrErrorInvalidScope, "API not published")
+                               }
+                       }
                }
        }
+       jwtToken, err := s.keycloak.GetToken(accessTokenReq.ClientId, *accessTokenReq.ClientSecret, *accessTokenReq.Scope, "invokerrealm")
+       if err != nil {
+               return sendAccessTokenError(ctx, http.StatusBadRequest, securityapi.AccessTokenErrErrorUnauthorizedClient, err.Error())
+       }
 
        accessTokenResp := securityapi.AccessTokenRsp{
-               AccessToken: "asdadfsrt dsr t5",
-               ExpiresIn:   0,
-               Scope:       &scope,
+               AccessToken: jwtToken.AccessToken,
+               ExpiresIn:   common29122.DurationSec(jwtToken.ExpiresIn),
+               Scope:       accessTokenReq.Scope,
                TokenType:   "Bearer",
        }
 
-       err := ctx.JSON(http.StatusCreated, accessTokenResp)
+       err = ctx.JSON(http.StatusCreated, accessTokenResp)
        if err != nil {
                // Something really bad happened, tell Echo that our handler failed
                return err
@@ -105,11 +123,10 @@ func (s *Security) PostTrustedInvokersApiInvokerIdUpdate(ctx echo.Context, apiIn
        return ctx.NoContent(http.StatusNotImplemented)
 }
 
-func sendCoreError(ctx echo.Context, code int, message string) error {
-       pd := common29122.ProblemDetails{
-               Cause:  &message,
-               Status: &code,
+func sendAccessTokenError(ctx echo.Context, code int, err securityapi.AccessTokenErrError, message string) error {
+       accessTokenErr := securityapi.AccessTokenErr{
+               Error:            err,
+               ErrorDescription: &message,
        }
-       err := ctx.JSON(code, pd)
-       return err
+       return ctx.JSON(code, accessTokenErr)
 }